copier icon indicating copy to clipboard operation
copier copied to clipboard

Add an OS specific helper for replacing characters for file separators

Open jkleve opened this issue 3 years ago • 3 comments

From a discussion we had about creating a directory structure, it was proposed to use replace(".", "/") in a task script. As this is specific to unix like filesystems it would be nice to have a helper that is OS specific. On Windows it will be \ and on unix like OS' it'll be /.

The working example (unix specific) is

# task.sh.jinja
templates_dir=templates
src_dir=src/main/{{ package.replace(".", "/") }}
test_dir=src/test/{{ package.replace(".", "/") }}

mkdir -p "$src_dir"
mkdir -p "$test_dir"

A nice alternative, as proposed by @yajo & @pawamoy would be

# task.sh.jinja
templates_dir=templates
src_dir=src/main/{{ package.replace(".", copier_sep) }}
test_dir=src/test/{{ package.replace(".", copier_sep) }}

mkdir -p "$src_dir"
mkdir -p "$test_dir"

jkleve avatar Jun 08 '22 07:06 jkleve

I don't think the distinction between Linux and Windows is relevant: indeed, the point of this issue is to provide a way to create directory structures without tasks, and the suggestion is to provide a context variable (for example copier_sep or os_sep) that is not a real OS separator (because they are not allowed in filenames), and that Copier will handle as if it was an actual separator. So in any case, users will use a single variable, whatever the OS is, and Copier will run Python's mkdir, where / works on all systems anyway.

pawamoy avatar Jun 08 '22 07:06 pawamoy

I see. You were pushing to add a feature where we can do this as a task in copier.yml instead of in a shell script?

jkleve avatar Jun 08 '22 09:06 jkleve

IIUC, what @yajo suggested is that Copier natively supports creating arbitrarily deep directories without tasks, yes, by allowing writers to use a copier_sep/os_sep constant in their filenames.

pawamoy avatar Jun 08 '22 10:06 pawamoy

umm... this works for me. You can use forward slash on Windows, no problem. I just made a custom jinja extension with a global DIR_SEP='/' and Copier creates directory structure.

rafalkrupinski avatar Jan 19 '23 22:01 rafalkrupinski

Oh, and I had to add one line to copier, as it doesn't create parent directories for rendered files. I'll prepare a patch

rafalkrupinski avatar Jan 20 '23 19:01 rafalkrupinski

In the PR 6e06df7 there's a test for this behaviour. It passes sep: '/' as part of data

rafalkrupinski avatar Jan 21 '23 15:01 rafalkrupinski

@yajo @pawamoy , Do you think Copier should provide a separator variable to facilitate this?

rafalkrupinski avatar Jan 21 '23 17:01 rafalkrupinski

Yes definitely. And it makes sense that it doesn't need to be a special character, since filenames will use the variable and not the character (slash) itself :)

pawamoy avatar Jan 21 '23 17:01 pawamoy

Yes definitely. And it makes sense that it doesn't need to be a special character, since filenames will use the variable and not the character (slash) itself :)

Introducing a global variable would break existing templates for anyone who already uses that name, regardless of what name we pick. So it would be a breaking change, unless there's a configuration variable: copier.yaml:

_separator_key: os_sep

WDYT?

rafalkrupinski avatar Jan 21 '23 18:01 rafalkrupinski

I think the risk of clashing with the name of an answer in someone's template is very low, especially if we prefix it with an underscore. But I'll let @yajo decide :slightly_smiling_face:

pawamoy avatar Jan 21 '23 19:01 pawamoy

I think the risk of clashing with the name of an answer in someone's template is very low, especially if we prefix it with an underscore. But I'll let @yajo decide 🙂

Ah, I didn't think of adding a prefixed variable. Yeah, that works.

In that case, how about exposing a subset of os as _os? I can think os.environ might be useful. Either way'd we have a "hook" for future os-specific extensions.

rafalkrupinski avatar Jan 21 '23 20:01 rafalkrupinski

Ha, very interesting idea :thinking:

pawamoy avatar Jan 21 '23 20:01 pawamoy

I can think os.environ might be useful

There's https://pypi.org/project/jinja2-getenv-extension/ so we shouldn't need this.

yajo avatar Jan 26 '23 18:01 yajo