Browser and install GUI for cookiecutter templates

⌈⌋ ⎇ branch:  cookiedough


Check-in [cf74a883a3]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Implement patch for cookiecutter/config.py (xdg paths)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | 0.0.9
Files: files | file ages | folders
SHA3-256: cf74a883a38714808571178e4f751b02f00319e0ff2c58b44c544ee5d2ad00d9
User & Date: mario 2021-03-22 18:12:38
Context
2021-03-23
15:10
Updated help pages, and update method check-in: 0446dd68e4 user: mario tags: trunk
2021-03-22
18:12
Implement patch for cookiecutter/config.py (xdg paths) check-in: cf74a883a3 user: mario tags: trunk, 0.0.9
18:11
Removed remnants of previous attempts of search input widget prettification check-in: 0adcc047dd user: mario tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added cookiedough/config.patch.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# api: patch
# description: apply onto .../site-packages/cookiecutter/ for xdg support

--- config.py	2021-03-22 14:55:25.449840370 +0100
+++ config.py	2021-03-22 15:00:20.738897569 +0100
@@ -10,6 +10,7 @@
 import collections
 
 import poyo
+import appdirs
 
 from cookiecutter.exceptions import ConfigDoesNotExistException
 from cookiecutter.exceptions import InvalidConfiguration
@@ -17,7 +18,7 @@
 
 logger = logging.getLogger(__name__)
 
-USER_CONFIG_PATH = os.path.expanduser('~/.cookiecutterrc')
+USER_CONFIG_PATH = appdirs.user_config_dir('cookiecutter', 'cookiecutter') + "/config"
 
 BUILTIN_ABBREVIATIONS = {
     'gh': 'https://github.com/{0}.git',
@@ -26,8 +27,8 @@
 }
 
 DEFAULT_CONFIG = {
-    'cookiecutters_dir': os.path.expanduser('~/.cookiecutters/'),
-    'replay_dir': os.path.expanduser('~/.cookiecutter_replay/'),
+    'cookiecutters_dir': appdirs.user_cache_dir("cookiecutters", "cookiecutters"),
+    'replay_dir': appdirs.user_config_dir('cookiecutter', 'cookiecutter') + "/replay/",
     'default_context': collections.OrderedDict([]),
     'abbreviations': BUILTIN_ABBREVIATIONS,
 }

Changes to cookiedough/rollout.py.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#     { name: no_params, type: bool, value: 0, description: Don't prompt for template vars. Use terminal prompts instead., help: You mgiht as well use cookiecutter directly then. }
#     { name: update_ccjson, type: bool, value: 1, description: Update parameters from cookiecutter.json files, help: avoids extra prompts if template infos outdated }
#     { name: hook_prompt, type: bool, value: 1, description: Display any additional prompts as GUI inputs, help: hook prompt.* functions }
# priority: core
# depends: python:cookiecutter
#
# Implements the parameter input window before incoking cookiecutter(1)
# for extracting a template. Also hooks cookiercutter.prompt.* functions,
# to avoid terminal prompts.
#


import sys, os, re, json
import PySimpleGUI as sg
import requests, appdirs







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#     { name: no_params, type: bool, value: 0, description: Don't prompt for template vars. Use terminal prompts instead., help: You mgiht as well use cookiecutter directly then. }
#     { name: update_ccjson, type: bool, value: 1, description: Update parameters from cookiecutter.json files, help: avoids extra prompts if template infos outdated }
#     { name: hook_prompt, type: bool, value: 1, description: Display any additional prompts as GUI inputs, help: hook prompt.* functions }
# priority: core
# depends: python:cookiecutter
#
# Implements the parameter input window before incoking cookiecutter(1)
# for extracting a template. Also hooks cookiecutter.prompt.* functions,
# to avoid terminal prompts.
#


import sys, os, re, json
import PySimpleGUI as sg
import requests, appdirs
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    "hook_prompt": True,
}


# finally, this is where cookiecutter gets invoked,
# params={} from the input window
def cutting(repo_url, params):

    # doc: https://cookiecutter.readthedocs.io/en/1.7.2/advanced/calling_from_python.html
    import cookiecutter.main
    cookiecutter.main.cookiecutter(
        template=repo_url,
        #checkout=None,
        no_input=True if params else False,
        extra_context=params,
        #replay=None,
        #overwrite_if_exists=False,
        #output_dir='.',
        #config_file=None,
        #default_config=False,
        #password=None,
        #directory=None,                 #@todo: watch out if those exist yet, workaround with http://repo.git/?dir=template2/
        #skip_if_file_exists=False,
        #accept_hooks=True,
    )

# override cookiecutter.prompt.* functions - rather than having click.prompt() CLI inputs







>










|
|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    "hook_prompt": True,
}


# finally, this is where cookiecutter gets invoked,
# params={} from the input window
def cutting(repo_url, params):
    ccc = CookieCutterConfig()
    # doc: https://cookiecutter.readthedocs.io/en/1.7.2/advanced/calling_from_python.html
    import cookiecutter.main
    cookiecutter.main.cookiecutter(
        template=repo_url,
        #checkout=None,
        no_input=True if params else False,
        extra_context=params,
        #replay=None,
        #overwrite_if_exists=False,
        #output_dir='.',
        config_file=ccc.fn,
        default_config=ccc.default_config(),
        #password=None,
        #directory=None,                 #@todo: watch out if those exist yet, workaround with http://repo.git/?dir=template2/
        #skip_if_file_exists=False,
        #accept_hooks=True,
    )

# override cookiecutter.prompt.* functions - rather than having click.prompt() CLI inputs
192
193
194
195
196
197
198
199






















200




201






202



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
class CookieCutterConfig():
    """ fix xdg support for cookiecutter """
    
    def __init__(self):
        self.dir = appdirs.user_config_dir("cookiecutter", "cookiecutter")
        self.fn = self.dir + "/config"
        self.replay = self.dir + "/replay"
        self.cache = appdirs.user_cache_dir("cookiecutters", "cookiecutter")






















        self.create(self.replay, self.cache)











    def create(self, *dirs):



        for dir in dirs:
            if not os.path.exists(dir):
                os.makedirs(dir, 0o755, True)

    default_config = dedent("""
        default_context:
            full_name: "Susan Examplary"
            email: "susan@example.com"
            github_username: "subs54"
        cookiecutters_dir: "/home/subs/.cache/cookiecutters/"
        replay_dir: "/home/subs/.config/cookiecutter/replay/"
    """)

    def patch(self):
        ...
        find(".../site-packages/cookiecutter/config.py")

        patch = dedent("""
        --- .../site-packages/cookiecutter/config.py	2020-05-10 04:20:05.298611402 +0200
        +++ .../cookiecutter/xdg-compliant-config.py	2021-03-22 00:00:00.835533776 +0100
        @@ -17,7 +17,7 @@
         
         logger = logging.getLogger(__name__)
         
        -USER_CONFIG_PATH = os.path.expanduser('~/.cookiecutterrc')
        +USER_CONFIG_PATH = os.path.expanduser('~/.config/cookiecutter/rc')
         
         BUILTIN_ABBREVIATIONS = {
             'gh': 'https://github.com/{0}.git',
        @@ -26,8 +26,8 @@
         }
         
         DEFAULT_CONFIG = {
        -    'cookiecutters_dir': os.path.expanduser('~/.cookiecutters/'),
        -    'replay_dir': os.path.expanduser('~/.cookiecutter_replay/'),
        +    'cookiecutters_dir': os.path.expanduser('~/.cache/cookiecutters/'),
        +    'replay_dir': os.path.expanduser('~/.config/cokiecutter/replay/'),
             'default_context': collections.OrderedDict([]),
             'abbreviations': BUILTIN_ABBREVIATIONS,
         }
        """)
        
        #os.system(f"patch -b -d {cc_base} < {patch_fn}")

        move = [
            ("~/.cookiecutterrc", "~/.config/cookiecutter/rc"),
            ("~/.cookiecutters/", "~/.cache/cookiecutters/"),
            ("~/.cookiecutter_replay/", "~/.config/cokiecutter/replay/"),
        ]








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>

>
>
>



|
<
<
<
<
<
<
<
<

<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242








243



244




245

246


247























class CookieCutterConfig():
    """ fix xdg support for cookiecutter """
    
    def __init__(self):
        self.dir = appdirs.user_config_dir("cookiecutter", "cookiecutter")
        self.fn = self.dir + "/config"
        self.replay = self.dir + "/replay"
        self.cache = appdirs.user_cache_dir("cookiecutters", "cookiecutters")
    
    def default_config(self):
        """ supply overrides per cookiecutter.main(default_config=…) """
        return {
            "default_context": {
                "full_name": "Susan Exemplary",
                "email": "sample@example.com",
                "github_username": "samp54",
            },
            "cookiecutters_dir": self.cache,
            "replay_dir": self.replay,
        }

    def patch(self):
        """ fix cookiecutter/config.py in-place """
        import cookiecutter.config
        target_dir = re.sub("[\w.]+$", "", cookiecutter.config.__file__)
        patch_file = re.sub("[\w.]+$", "config.patch", __file__)
        os.system(f"patch -b -d {target_dir} < {patch_file}")

    def move(self):
        """ shuffle old locations to new """
        self.create(self.dir)
        from_to = {
            "~/.cookiecutterrc": self.fn,
            "~/.cookiecutters/": self.cache,
            "~/.cookiecutter_replay/": self.replay,
        }
        for orig, new in from_to.items():
            orig = os.path.expanduser(orig)
            if os.path.exists(orig) and not os.path.exists(new):
                os.rename(orig, new)
                self.nobackup(new)

    def create(self, *dirs):
        """ create config+cache dirs, if missing """
        if not dirs:
            dirs = [self.replay, self.cache]
        for dir in dirs:
            if not os.path.exists(dir):
                os.makedirs(dir, 0o755, True)
                self.nobackup(dir)












    def nobackup(self, dir):




        """ touch .nobackkup for cache dir """

        if dir.find("/.cache/") > 0:


             open(dir + "/.nobackup", "a").close()