1
1
from __future__ import annotations
2
2
3
3
import os
4
+ from collections .abc import Iterable
4
5
from datetime import datetime
5
6
from typing import Any
6
7
9
10
from jinja2 import StrictUndefined
10
11
from jinja2 import Template
11
12
13
+ from babelizer ._datadir import get_template_dir
12
14
from babelizer ._post_hook import run
13
15
from babelizer ._utils import as_cwd
14
16
15
17
16
18
def cookiecutter (
17
19
template : str ,
18
- extra_context : dict [str , Any ] | None = None ,
20
+ context : dict [str , Any ] | None = None ,
19
21
output_dir : str = "." ,
20
- no_input : bool = True ,
21
- overwrite_if_exists : bool = False ,
22
22
) -> None :
23
- if extra_context is None :
24
- extra_context = {}
25
- env = Environment ( loader = FileSystemLoader ( template ), undefined = StrictUndefined )
23
+ if context is None :
24
+ context = {}
25
+ env = babelizer_environment ( template )
26
26
27
27
def datetime_format (value : datetime , format_ : str = "%Y-%M-%D" ) -> str :
28
28
return value .strftime (format_ )
@@ -31,30 +31,62 @@ def datetime_format(value: datetime, format_: str = "%Y-%M-%D") -> str:
31
31
32
32
for dirpath , _dirnames , filenames in os .walk (template ):
33
33
rel_path = os .path .relpath (dirpath , template )
34
- target_dir = os .path .join (output_dir , render_path (rel_path , extra_context ))
34
+ target_dir = os .path .join (output_dir , render_path (rel_path , context ))
35
35
36
36
if not os .path .exists (target_dir ):
37
37
os .makedirs (target_dir )
38
38
39
39
for filename in filenames :
40
- target_path = os .path .join (target_dir , render_path (filename , extra_context ))
40
+ target_path = os .path .join (target_dir , render_path (filename , context ))
41
41
42
42
with open (target_path , "w" ) as fp :
43
43
fp .write (
44
- env .get_template (os .path .join (rel_path , filename )).render (
45
- ** extra_context
46
- )
44
+ env .get_template (os .path .join (rel_path , filename )).render (** context )
47
45
)
48
46
49
47
with as_cwd (output_dir ):
50
- run (extra_context )
51
-
52
-
53
- def render_path (path : str , context : dict [str , Any ]) -> str :
54
- rendered_path = Template (path ).render (** context )
48
+ run (context )
49
+
50
+
51
+ def babelizer_environment (template : str | None = None ) -> Environment :
52
+ if template is None :
53
+ template = get_template_dir ()
54
+
55
+ return Environment (loader = FileSystemLoader (template ), undefined = StrictUndefined )
56
+
57
+
58
+ def render_path (
59
+ path : str ,
60
+ context : dict [str , Any ],
61
+ remove_extension : Iterable [str ] = (".jinja" , ".jinja2" , ".j2" ),
62
+ ) -> str :
63
+ """Render a path as though it were a jinja template.
64
+
65
+ Parameters
66
+ ----------
67
+ path : str
68
+ A path.
69
+ context : dict
70
+ Context to use for substitution.
71
+ remove_extension : iterable of str, optional
72
+ If the provided path ends with one of these exensions,
73
+ the extension will be removed from the rendered path.
74
+
75
+ Examples
76
+ --------
77
+ >>> from babelizer._cookiecutter import render_path
78
+ >>> render_path("{{foo}}.py", {"foo": "bar"})
79
+ 'bar.py'
80
+ >>> render_path("{{foo}}.py.jinja", {"foo": "bar"})
81
+ 'bar.py'
82
+ >>> render_path("bar.py.j2", {"foo": "bar"})
83
+ 'bar.py'
84
+ >>> render_path("{{bar}}.py.jinja", {"foo": "bar"})
85
+ Traceback (most recent call last):
86
+ ...
87
+ jinja2.exceptions.UndefinedError: 'bar' is undefined
88
+ """
89
+ rendered_path = Template (path , undefined = StrictUndefined ).render (** context )
55
90
56
91
root , ext = os .path .splitext (rendered_path )
57
- if ext == ".jinja" :
58
- rendered_path = root
59
-
60
- return rendered_path
92
+ return rendered_path if ext not in remove_extension else root
0 commit comments