prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Need help with generating GUID/UUID values for context variables
  * 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: #60, #102, #180, #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 (#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
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `cookiecutter/extensions.py`
  Content:
  ```
  1 """Jinja2 extensions."""
  2 import json
  3 import string
  4 from secrets import choice
  5 
  6 from jinja2.ext import Extension
  7 from slugify import slugify as pyslugify
  8 
  9 
  10 class JsonifyExtension(Extension):
  11     """Jinja2 extension to convert a Python object to JSON."""
  12 
  13     def __init__(self, environment):
  14         """Initialize the extension with the given environment."""
  15         super(JsonifyExtension, self).__init__(environment)
  16 
  17         def jsonify(obj):
  18             return json.dumps(obj, sort_keys=True, indent=4)
  19 
  20         environment.filters['jsonify'] = jsonify
  21 
  22 
  23 class RandomStringExtension(Extension):
  24     """Jinja2 extension to create a random string."""
  25 
  26     def __init__(self, environment):
  27         """Jinja2 Extension Constructor."""
  28         super(RandomStringExtension, self).__init__(environment)
  29 
  30         def random_ascii_string(length, punctuation=False):
  31             if punctuation:
  32                 corpus = "".join((string.ascii_letters, string.punctuation))
  33             else:
  34                 corpus = string.ascii_letters
  35             return "".join(choice(corpus) for _ in range(length))
  36 
  37         environment.globals.update(random_ascii_string=random_ascii_string)
  38 
  39 
  40 class SlugifyExtension(Extension):
  41     """Jinja2 Extension to slugify string."""
  42 
  43     def __init__(self, environment):
  44         """Jinja2 Extension constructor."""
  45         super(SlugifyExtension, self).__init__(environment)
  46 
  47         def slugify(value, **kwargs):
  48             """Slugifies the value."""
  49             return pyslugify(value, **kwargs)
  50 
  51         environment.filters['slugify'] = slugify
  52
  ```
  
  Path: `cookiecutter/environment.py`
  Content:
  ```
  1 """Jinja2 environment and extensions loading."""
  2 from jinja2 import Environment, StrictUndefined
  3 
  4 from cookiecutter.exceptions import UnknownExtension
  5 
  6 
  7 class ExtensionLoaderMixin(object):
  8     """Mixin providing sane loading of extensions specified in a given context.
  9 
  10     The context is being extracted from the keyword arguments before calling
  11     the next parent class in line of the child.
  12     """
  13 
  14     def __init__(self, **kwargs):
  15         """Initialize the Jinja2 Environment object while loading extensions.
  16 
  17         Does the following:
  18 
  19         1. Establishes default_extensions (currently just a Time feature)
  20         2. Reads extensions set in the cookiecutter.json _extensions key.
  21         3. Attempts to load the extensions. Provides useful error if fails.
  22         """
  23         context = kwargs.pop('context', {})
  24 
  25         default_extensions = [
  26             'cookiecutter.extensions.JsonifyExtension',
  27             'cookiecutter.extensions.RandomStringExtension',
  28             'cookiecutter.extensions.SlugifyExtension',
  29             'jinja2_time.TimeExtension',
  30         ]
  31         extensions = default_extensions + self._read_extensions(context)
  32 
  33         try:
  34             super(ExtensionLoaderMixin, self).__init__(extensions=extensions, **kwargs)
  35         except ImportError as err:
  36             raise UnknownExtension('Unable to load extension: {}'.format(err))
  37 
  38     def _read_extensions(self, context):
  39         """Return list of extensions as str to be passed on to the Jinja2 env.
  40 
  41         If context does not contain the relevant info, return an empty
  42         list instead.
  43         """
  44         try:
  45             extensions = context['cookiecutter']['_extensions']
  46         except KeyError:
  47             return []
  48         else:
  49             return [str(ext) for ext in extensions]
  50 
  51 
  52 class StrictEnvironment(ExtensionLoaderMixin, Environment):
  53     """Create strict Jinja2 environment.
  54 
  55     Jinja2 environment will raise error on undefined variable in template-
  56     rendering context.
  57     """
  58 
  59     def __init__(self, **kwargs):
  60         """Set the standard Cookiecutter StrictEnvironment.
  61 
  62         Also loading extensions defined in cookiecutter.json's _extensions key.
  63         """
  64         super(StrictEnvironment, self).__init__(undefined=StrictUndefined, **kwargs)
  65
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/cookiecutter/environment.py b/cookiecutter/environment.py
  --- a/cookiecutter/environment.py
  +++ b/cookiecutter/environment.py
  @@ -26,6 +26,7 @@
               'cookiecutter.extensions.JsonifyExtension',
               'cookiecutter.extensions.RandomStringExtension',
               'cookiecutter.extensions.SlugifyExtension',
  +            'cookiecutter.extensions.UUIDExtension',
               'jinja2_time.TimeExtension',
           ]
           extensions = default_extensions + self._read_extensions(context)
  diff --git a/cookiecutter/extensions.py b/cookiecutter/extensions.py
  --- a/cookiecutter/extensions.py
  +++ b/cookiecutter/extensions.py
  @@ -1,6 +1,7 @@
   """Jinja2 extensions."""
   import json
   import string
  +import uuid
   from secrets import choice
   
   from jinja2.ext import Extension
  @@ -49,3 +50,17 @@
               return pyslugify(value, **kwargs)
   
           environment.filters['slugify'] = slugify
  +
  +
  +class UUIDExtension(Extension):
  +    """Jinja2 Extension to generate uuid4 string."""
  +
  +    def __init__(self, environment):
  +        """Jinja2 Extension constructor."""
  +        super(UUIDExtension, self).__init__(environment)
  +
  +        def uuid4():
  +            """Generate UUID4."""
  +            return str(uuid.uuid4())
  +
  +        environment.globals.update(uuid4=uuid4)
  
verification_info: {"golden_diff": "diff --git a/cookiecutter/environment.py b/cookiecutter/environment.py\n--- a/cookiecutter/environment.py\n+++ b/cookiecutter/environment.py\n@@ -26,6 +26,7 @@\n             'cookiecutter.extensions.JsonifyExtension',\n             'cookiecutter.extensions.RandomStringExtension',\n             'cookiecutter.extensions.SlugifyExtension',\n+            'cookiecutter.extensions.UUIDExtension',\n             'jinja2_time.TimeExtension',\n         ]\n         extensions = default_extensions + self._read_extensions(context)\ndiff --git a/cookiecutter/extensions.py b/cookiecutter/extensions.py\n--- a/cookiecutter/extensions.py\n+++ b/cookiecutter/extensions.py\n@@ -1,6 +1,7 @@\n \"\"\"Jinja2 extensions.\"\"\"\n import json\n import string\n+import uuid\n from secrets import choice\n \n from jinja2.ext import Extension\n@@ -49,3 +50,17 @@\n             return pyslugify(value, **kwargs)\n \n         environment.filters['slugify'] = slugify\n+\n+\n+class UUIDExtension(Extension):\n+    \"\"\"Jinja2 Extension to generate uuid4 string.\"\"\"\n+\n+    def __init__(self, environment):\n+        \"\"\"Jinja2 Extension constructor.\"\"\"\n+        super(UUIDExtension, self).__init__(environment)\n+\n+        def uuid4():\n+            \"\"\"Generate UUID4.\"\"\"\n+            return str(uuid.uuid4())\n+\n+        environment.globals.update(uuid4=uuid4)\n", "issue": "Need help with generating GUID/UUID values for context variables\n* Cookiecutter version: 1.6\r\n* Template project url: none\r\n* Python version: 3.7 (virtual env created using win python 3.7 x64)\r\n* Operating System: Windows 10, 64 Bit\r\n\r\n### Description:\r\n\r\nFirst off many thanks for creating this project !\r\nHere is some context of what I am trying to do and where I need some guidance\r\n* 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\r\n* I was able to most of it working but for the below:\r\n* Parts of the above project, solution files involves generating several unique GUIDs\r\n* 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\r\n* I was however blocked as I could not figure out how to access the context being used by CC and the jinja2 engine \r\n* I proceeded to go over the many issues on github and found some related ones like the following: #60, #102, #180, #288 but no clear answer on how to achieve what I'd like\r\n* I also followed some others issues that suggested creating custom jinja2 extension/filter (#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\r\n* 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\r\n\r\nAppreciate any pointers on how I can inject GUID values for the context variables\n", "before_files": [{"content": "\"\"\"Jinja2 extensions.\"\"\"\nimport json\nimport string\nfrom secrets import choice\n\nfrom jinja2.ext import Extension\nfrom slugify import slugify as pyslugify\n\n\nclass JsonifyExtension(Extension):\n    \"\"\"Jinja2 extension to convert a Python object to JSON.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Initialize the extension with the given environment.\"\"\"\n        super(JsonifyExtension, self).__init__(environment)\n\n        def jsonify(obj):\n            return json.dumps(obj, sort_keys=True, indent=4)\n\n        environment.filters['jsonify'] = jsonify\n\n\nclass RandomStringExtension(Extension):\n    \"\"\"Jinja2 extension to create a random string.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Jinja2 Extension Constructor.\"\"\"\n        super(RandomStringExtension, self).__init__(environment)\n\n        def random_ascii_string(length, punctuation=False):\n            if punctuation:\n                corpus = \"\".join((string.ascii_letters, string.punctuation))\n            else:\n                corpus = string.ascii_letters\n            return \"\".join(choice(corpus) for _ in range(length))\n\n        environment.globals.update(random_ascii_string=random_ascii_string)\n\n\nclass SlugifyExtension(Extension):\n    \"\"\"Jinja2 Extension to slugify string.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Jinja2 Extension constructor.\"\"\"\n        super(SlugifyExtension, self).__init__(environment)\n\n        def slugify(value, **kwargs):\n            \"\"\"Slugifies the value.\"\"\"\n            return pyslugify(value, **kwargs)\n\n        environment.filters['slugify'] = slugify\n", "path": "cookiecutter/extensions.py"}, {"content": "\"\"\"Jinja2 environment and extensions loading.\"\"\"\nfrom jinja2 import Environment, StrictUndefined\n\nfrom cookiecutter.exceptions import UnknownExtension\n\n\nclass ExtensionLoaderMixin(object):\n    \"\"\"Mixin providing sane loading of extensions specified in a given context.\n\n    The context is being extracted from the keyword arguments before calling\n    the next parent class in line of the child.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        \"\"\"Initialize the Jinja2 Environment object while loading extensions.\n\n        Does the following:\n\n        1. Establishes default_extensions (currently just a Time feature)\n        2. Reads extensions set in the cookiecutter.json _extensions key.\n        3. Attempts to load the extensions. Provides useful error if fails.\n        \"\"\"\n        context = kwargs.pop('context', {})\n\n        default_extensions = [\n            'cookiecutter.extensions.JsonifyExtension',\n            'cookiecutter.extensions.RandomStringExtension',\n            'cookiecutter.extensions.SlugifyExtension',\n            'jinja2_time.TimeExtension',\n        ]\n        extensions = default_extensions + self._read_extensions(context)\n\n        try:\n            super(ExtensionLoaderMixin, self).__init__(extensions=extensions, **kwargs)\n        except ImportError as err:\n            raise UnknownExtension('Unable to load extension: {}'.format(err))\n\n    def _read_extensions(self, context):\n        \"\"\"Return list of extensions as str to be passed on to the Jinja2 env.\n\n        If context does not contain the relevant info, return an empty\n        list instead.\n        \"\"\"\n        try:\n            extensions = context['cookiecutter']['_extensions']\n        except KeyError:\n            return []\n        else:\n            return [str(ext) for ext in extensions]\n\n\nclass StrictEnvironment(ExtensionLoaderMixin, Environment):\n    \"\"\"Create strict Jinja2 environment.\n\n    Jinja2 environment will raise error on undefined variable in template-\n    rendering context.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        \"\"\"Set the standard Cookiecutter StrictEnvironment.\n\n        Also loading extensions defined in cookiecutter.json's _extensions key.\n        \"\"\"\n        super(StrictEnvironment, self).__init__(undefined=StrictUndefined, **kwargs)\n", "path": "cookiecutter/environment.py"}], "after_files": [{"content": "\"\"\"Jinja2 extensions.\"\"\"\nimport json\nimport string\nimport uuid\nfrom secrets import choice\n\nfrom jinja2.ext import Extension\nfrom slugify import slugify as pyslugify\n\n\nclass JsonifyExtension(Extension):\n    \"\"\"Jinja2 extension to convert a Python object to JSON.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Initialize the extension with the given environment.\"\"\"\n        super(JsonifyExtension, self).__init__(environment)\n\n        def jsonify(obj):\n            return json.dumps(obj, sort_keys=True, indent=4)\n\n        environment.filters['jsonify'] = jsonify\n\n\nclass RandomStringExtension(Extension):\n    \"\"\"Jinja2 extension to create a random string.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Jinja2 Extension Constructor.\"\"\"\n        super(RandomStringExtension, self).__init__(environment)\n\n        def random_ascii_string(length, punctuation=False):\n            if punctuation:\n                corpus = \"\".join((string.ascii_letters, string.punctuation))\n            else:\n                corpus = string.ascii_letters\n            return \"\".join(choice(corpus) for _ in range(length))\n\n        environment.globals.update(random_ascii_string=random_ascii_string)\n\n\nclass SlugifyExtension(Extension):\n    \"\"\"Jinja2 Extension to slugify string.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Jinja2 Extension constructor.\"\"\"\n        super(SlugifyExtension, self).__init__(environment)\n\n        def slugify(value, **kwargs):\n            \"\"\"Slugifies the value.\"\"\"\n            return pyslugify(value, **kwargs)\n\n        environment.filters['slugify'] = slugify\n\n\nclass UUIDExtension(Extension):\n    \"\"\"Jinja2 Extension to generate uuid4 string.\"\"\"\n\n    def __init__(self, environment):\n        \"\"\"Jinja2 Extension constructor.\"\"\"\n        super(UUIDExtension, self).__init__(environment)\n\n        def uuid4():\n            \"\"\"Generate UUID4.\"\"\"\n            return str(uuid.uuid4())\n\n        environment.globals.update(uuid4=uuid4)\n", "path": "cookiecutter/extensions.py"}, {"content": "\"\"\"Jinja2 environment and extensions loading.\"\"\"\nfrom jinja2 import Environment, StrictUndefined\n\nfrom cookiecutter.exceptions import UnknownExtension\n\n\nclass ExtensionLoaderMixin(object):\n    \"\"\"Mixin providing sane loading of extensions specified in a given context.\n\n    The context is being extracted from the keyword arguments before calling\n    the next parent class in line of the child.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        \"\"\"Initialize the Jinja2 Environment object while loading extensions.\n\n        Does the following:\n\n        1. Establishes default_extensions (currently just a Time feature)\n        2. Reads extensions set in the cookiecutter.json _extensions key.\n        3. Attempts to load the extensions. Provides useful error if fails.\n        \"\"\"\n        context = kwargs.pop('context', {})\n\n        default_extensions = [\n            'cookiecutter.extensions.JsonifyExtension',\n            'cookiecutter.extensions.RandomStringExtension',\n            'cookiecutter.extensions.SlugifyExtension',\n            'cookiecutter.extensions.UUIDExtension',\n            'jinja2_time.TimeExtension',\n        ]\n        extensions = default_extensions + self._read_extensions(context)\n\n        try:\n            super(ExtensionLoaderMixin, self).__init__(extensions=extensions, **kwargs)\n        except ImportError as err:\n            raise UnknownExtension('Unable to load extension: {}'.format(err))\n\n    def _read_extensions(self, context):\n        \"\"\"Return list of extensions as str to be passed on to the Jinja2 env.\n\n        If context does not contain the relevant info, return an empty\n        list instead.\n        \"\"\"\n        try:\n            extensions = context['cookiecutter']['_extensions']\n        except KeyError:\n            return []\n        else:\n            return [str(ext) for ext in extensions]\n\n\nclass StrictEnvironment(ExtensionLoaderMixin, Environment):\n    \"\"\"Create strict Jinja2 environment.\n\n    Jinja2 environment will raise error on undefined variable in template-\n    rendering context.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        \"\"\"Set the standard Cookiecutter StrictEnvironment.\n\n        Also loading extensions defined in cookiecutter.json's _extensions key.\n        \"\"\"\n        super(StrictEnvironment, self).__init__(undefined=StrictUndefined, **kwargs)\n", "path": "cookiecutter/environment.py"}]}