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

Need help with generating GUID/UUID values for context variables #1101

Closed
chechu2k5 opened this issue Sep 9, 2018 · 11 comments · Fixed by #1493
Closed

Need help with generating GUID/UUID values for context variables #1101

chechu2k5 opened this issue Sep 9, 2018 · 11 comments · Fixed by #1493

Comments

@chechu2k5
Copy link

chechu2k5 commented Sep 9, 2018

  • Cookiecutter version: 1.6
  • Template project url: none
  • Python version: 3.7 (virtual env created using win python 3.7 x64)
  • Operating System: Windows 10, 64 Bit

Description:

First off many thanks for creating this project !
Here is some context of what I am trying to do and where I need some guidance

  • I am trying to use CC to generate new a Visual Studio 2017 solution and project files with a particular folder/file organization that I like
  • I was able to most of it working but for the below:
  • Parts of the above project, solution files involves generating several unique GUIDs
  • my first approach was creating a pre_gen_project.py inside the hooks folder and update/create new variables that could be added to the ones loaded from cookiecutter.json or entered by the user
  • I was however blocked as I could not figure out how to access the context being used by CC and the jinja2 engine
  • I proceeded to go over the many issues on github and found some related ones like the following: Context injection from pre hook / access from post hook #60, run hooks through template allowing for dynamic contexting in pre/post hooks #102, Add ability to inject context in pre-generate hooks #180, Inject context into hooks #288 but no clear answer on how to achieve what I'd like
  • I also followed some others issues that suggested creating custom jinja2 extension/filter (Allow Jinja extensions to be defined/bundled in the template repository #944) but I couldnt figure out how or where to put them in the template folder so the cookiecutter.exe can identify them and pick them up
  • Lastly, I also tried going over the CC source code and tried to create a new executable from my script (similar to cli.py) that passes the guids via the extra_context to cookiecutter.main(...) but ran into some other problems that I am still trying to figure out

Appreciate any pointers on how I can inject GUID values for the context variables

@glenfant
Copy link

Computing new Jinja context variables in the pre hook would be a great feature.

@gmr
Copy link

gmr commented Nov 1, 2018

Having a pre-hook for computing values that are injected into the context for use in templates would be very useful.

@agrant3d
Copy link

Was also looking to do this exact thing. Fixing the vcxproj in a post hook script is not too hard, but I have other cases where I need to generate unique ids in unstructured files (cpp).

I was surprised when I started using cookiecutter that the scripts are rendered and ran from temp folder, rather than simply importing the script and giving access to the context dict. Seems like that would make it much simpler and more powerful!

@agrant3d
Copy link

As a solution, what I do is: in pre_gen_project.py I generate my ids, and write them to a tmp file inside the template. Then I {%- include tmp/IDFILE.txt -%} where needed. In post_gen_project.py I cleanup the tmp folder.

@rymurr
Copy link

rymurr commented Feb 18, 2019

@agrant3d could you show a bit more of your code? I used pre_gen_project.py to write a file at tmp/id1.txt and I am doing {%- include 'tmp/id1.txt' =%} from file a/b/c.xml and its giving me a TemplateNotFound exception

@agrant3d
Copy link

Sure, looks something like this:

import os
import uuid

CURDIR = os.path.realpath(os.path.curdir)
TEMPLATEDIR = os.path.normpath(os.path.join(CURDIR, '..', '{{cookiecutter._template}}'))
TMPDIR = os.path.join(TEMPLATEDIR, '{{'{{'}}cookiecutter.project_slug{{'}}'}}', 'tmp')

GUIDS = ['PROJECT_GUID', 'SOLUTION_GUID']
for guid in GUIDS:
    file_path = os.path.join(TMPDIR, guid + '.txt')
    with open(file_path, 'w') as f:
        f.write("{" + str(uuid.uuid4()).upper() + "}")

The thing you're probably missing is that you need to put the files inside the {{cookiecutter.project_slug}} directory.

@agrant3d
Copy link

Note - this method only works when you are working with a local copy of the cookiecutter template. If it's a cached version - you cannot simply write to the directory.

@rymurr
Copy link

rymurr commented Feb 24, 2019

worked a dream, thanks @agrant3d

@metaskills
Copy link

I am trying to write some Lambda CookieCutter projects because AWS SAM uses this project. Though I do like a good challenge, I've not had a fun time at it. Hoping someone can help.

I need to take the project_name and derive folder/file names, as well as Ruby class names to match in my project. I really wish #944 was merged and I'd be able to use some Python inflector code and do what I need in the templates. Of course #60 would have been helpful too. But I've been forced to try the method above using pre/post hooks to write files to include. I cant get it working. I keep ending up with a jinja2.exceptions.TemplateNotFound: tmp/class_name.txt error.

Note - this method only works when you are working with a local copy of the cookiecutter template. If it's a cached version - you cannot simply write to the directory.

So my cookiecutter._tempalte value is gh:customink/lambda-starter-ruby. My guess is that I'd have to write to ~/.cookiecutters/lambda-starter-ruby where the cloned repo is for this to work?

@metaskills
Copy link

Confirmed on putting these tmp files in the ~/.cookiecutters directory. My pre_gen_project.py file is basically the inflector code I needed followed by this.

project_name  = '{{cookiecutter.project_name}}'
cc_template   = '{{cookiecutter._template}}'
template_name = cc_template.split("/")[-1]

file_name  = singularize(tableize(project_name))
class_name = singularize(camelize(tableize(project_name)))
dash_name  = singularize(dasherize(project_name))
all_names  = {
  'file_name': file_name,
  'class_name': class_name,
  'dash_name': dash_name
}

import os
import pathlib
from os.path import expanduser
home_dir = expanduser("~")
template_dir = os.path.join(home_dir, '.cookiecutters', template_name)
temp_dir = os.path.join(template_dir, '{{'{{'}}cookiecutter.project_name{{'}}'}}', '_cctmp')
pathlib.Path(temp_dir).mkdir(parents=True, exist_ok=True)

for name in all_names.keys():
  file_path = os.path.join(temp_dir, name + '.txt')
  with open(file_path, 'w') as f:
    f.write(all_names[name])

@RobRoseKnows
Copy link

Looks like there's a PR out to fix this by @jonaswre in #1493

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

Successfully merging a pull request may close this issue.

7 participants