-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Document how to do conditional files/directories #723
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
Comments
Yeah I needed this a while ago, and came up with an approach similar to 1:
{
"project": "my-project",
"feature1": [true, false],
"feature2": [true, false],
"feature3": [true, false]
}
Note:
features:
- name: feature1
enabled: {{cookiecutter.feature1|lower}}
resources:
- path/to/file/Feature1a.txt
- path/to/file/Feature1b.txt
- name: feature2
enabled: {{cookiecutter.feature2|lower}}
resources:
- path/to/file/Feature2.txt
- name: feature3
enabled: {{cookiecutter.feature3|lower}}
resources:
- path/to/file/feature/three/folder
#!/usr/bin/env python
import os
import shutil
import yaml
MANIFEST = "manifest.yml"
def delete_resources_for_disabled_features():
with open(MANIFEST) as manifest_file:
manifest = yaml.load(manifest_file)
for feature in manifest['features']:
if not feature['enabled']:
print "removing resources for disabled feature {}...".format(feature['name'])
for resource in feature['resources']:
delete_resource(resource)
print "cleanup complete, removing manifest..."
delete_resource(MANIFEST)
def delete_resource(resource):
if os.path.isfile(resource):
print "removing file: {}".format(resource)
os.remove(resource)
elif os.path.isdir(resource):
print "removing directory: {}".format(resource)
shutil.rmtree(resource)
if __name__ == "__main__":
delete_resources_for_disabled_features() |
@jamesbassett what if you can't know absolute path to project created from template? I digged into cookiecutter source code and found that there is no way for hooks to get to know generated project fs path — https://github.com/audreyr/cookiecutter/blob/master/cookiecutter/hooks.py#L53 What did I miss? |
@gvidon the resource paths in my manifest aren't absolute - they're relative to the generated output directory (in my case they look something like As an aside, I believe cookiecutter changes directory to the output directory, so if you need to, you can access the generated directory that way from a hook as well. |
In the OP:
How does that work, and why does it not work on Windows? |
The solution in this thread wasn't quite clear to me, so for anybody else landing here from google:
# cat post_gen_project.py
import os
import shutil
print(os.getcwd()) # prints /absolute/path/to/{{cookiecutter.project_slug}}
def remove(filepath):
if os.path.isfile(filepath):
os.remove(filepath)
elif os.path.isdir(filepath):
shutil.rmtree(filepath)
create_readme = '{{cookiecutter.create_readme}}' == 'y'
create_file_one = '{{cookiecutter.create_file_one}}' == 'y'
create_file_two = '{{cookiecutter.create_file_two}}' == 'y'
if not create_readme:
# remove top-level file inside the generated folder
remove('README.md')
if not create_file_one:
# remove absolute path to file nested inside the generated folder
remove(os.path.join(os.getcwd(), '{{cookiecutter.package_name}}', 'file_one.py'))
if not create_file_two:
# remove relative file nested inside the generated folder
remove(os.path.join('{{cookiecutter.package_name}}', 'file_two.py')) |
@jgonggrijp I got curious how the conditional files work as well. After a little playing around, it's actually super simple: just use an My guess is this doesn't work on Windows because |
After a little more playing: making entire files conditional using |
This is just a quick note to indicate: has broken links as of this post (2019-09-28 09:36:00). Another option that was not enumerated in the referenced post, but is now also available:
|
Not sure the issue you're finding on Windows. At least on Windows 10 filenames with if conditionals in them do work. For example I have a file called: Hope this helps others on windows who read the above comment and assume they have to start messing around with post scripts. |
We can also use if-expressions $ cat conditional/cookiecutter.json; tree conditional; cookiecutter -f --no-input conditional; tree sceletor
{
"project_name": "sceletor",
"generate_this": "y"
}
conditional
├── cookiecutter.json
└── {{cookiecutter.project_name}}
└── {{\ 'test-this.txt'\ if\ cookiecutter.generate_this\ ==\ 'y'\ else\ ''\ }}
sceletor
└── test-this.txt
|
Any example somewhere @dreftymac ? |
I made some notes on this here: https://til.simonwillison.net/cookiecutter/conditionally-creating-directories |
This is an old issue, but seems to be a feature that folks (including me) really need. I've crafted this Jinja extension named cut-out-cookies adds a 'stencil' filter that can be used in filename to optionally include it. For directories, you need to use the 'stencil_path' filter along with a post-gen hook due to this issue. The package is installable from pypi. The project includes an example structure and the README covers how to use the features. |
This is nice and indeed, Windows 10 supports that perfectly fine... But you'll run into issues with Git. I did not manage to commit such files into version control. Also many editors refuse to load and process files with such "odd" names. It would be much cleaner to have a convention that empty files are not added to the generated project. |
Probably because you didn't have any files inside the directory. Empty folders are not recognized by git. |
An empty |
I made #2095 which should enable the ability to skip directories in the same way as skipping files. |
If you want to handle conditional files with Say you have the following boolean switch in
Then in any optional file you would wrap the content in an
When you run Then the only task
|
In the advanced_usage.rst document we should document the following techniques:
The text was updated successfully, but these errors were encountered: