Skip to content

Commit e445199

Browse files
authored
fix: copier delay computation (#587)
* fix: copier delay computation Signed-off-by: Henry Schreiner <[email protected]> * fix: use smarter dict wrapper Signed-off-by: Henry Schreiner <[email protected]> --------- Signed-off-by: Henry Schreiner <[email protected]>
1 parent 4eb108f commit e445199

File tree

3 files changed

+69
-20
lines changed

3 files changed

+69
-20
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,19 @@ projects.
6868
Install `copier` and `copier-templates-extensions`. Using [uv][], that's:
6969

7070
```bash
71-
uv tool install 'copier!=9.7.*' --with copier-templates-extensions
71+
uv tool install --with copier-templates-extensions copier
7272
```
7373

74-
(Copier 9.5.0 [has a bug](https://github.com/copier-org/copier/issues/1977), and
75-
9.7.0/9.7.1 [also have one](https://github.com/copier-org/copier/issues/2113))
76-
7774
Now, run copier to generate your project:
7875

7976
```bash
8077
copier copy gh:scientific-python/cookie <pkg> --trust --vcs-ref=HEAD
8178
```
8279

8380
(`<pkg>` is the path to put the new project. `--vcs-ref=HEAD` gets the current
84-
version instead of the last tag, matching cookiecutter's behavior.)
81+
version instead of the last tag, matching cookiecutter's behavior. Note you can
82+
combine these two lines into one with `uvx`, just remember to pass `--with`
83+
before the program name in that case.)
8584

8685
You will get a nicer CLI experience with answer validation. You will also get a
8786
`.copier-answers.yml` file, which will allow you to perform updates in the

helpers/extensions.py

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,71 @@
11
import datetime
2+
from collections.abc import Mapping
23

34
from copier_templates_extensions import ContextHook
45

56

7+
class SmartDict(Mapping):
8+
def __init_subclass__(cls):
9+
cls._computed_keys = {}
10+
11+
def __init__(self, init):
12+
self._init = init
13+
14+
@classmethod
15+
def register(cls, func):
16+
cls._computed_keys[func.__name__] = func
17+
return func
18+
19+
def __getitem__(self, item):
20+
if item in self._computed_keys:
21+
return self._computed_keys[item](self._init)
22+
23+
return self._init[item]
24+
25+
def __contains__(self, item):
26+
return item in self._init or item in self._computed_keys
27+
28+
def __iter__(self):
29+
yield from self._init
30+
yield from self._computed_keys
31+
32+
def __len__(self):
33+
return len(self._computed_keys) + len(self._init)
34+
35+
36+
class CookiecutterContext(SmartDict):
37+
pass
38+
39+
40+
@CookiecutterContext.register
41+
def __year(_):
42+
return str(datetime.datetime.today().year)
43+
44+
45+
@CookiecutterContext.register
46+
def __ci(context):
47+
return "github" if "github.com" in context["url"] else "gitlab"
48+
49+
50+
@CookiecutterContext.register
51+
def __project_slug(context):
52+
return context["project_name"].lower().replace("-", "_").replace(".", "_")
53+
54+
55+
@CookiecutterContext.register
56+
def __type(context):
57+
return (
58+
"compiled"
59+
if context["backend"] in {"pybind11", "skbuild", "mesonpy", "maturin"}
60+
else "pure"
61+
)
62+
63+
64+
@CookiecutterContext.register
65+
def __answers(context):
66+
return context["_copier_conf"]["answers_file"]
67+
68+
669
class CookiecutterNamespace(ContextHook):
770
def hook(self, context):
8-
context["__year"] = str(datetime.datetime.today().year)
9-
context["__project_slug"] = (
10-
context["project_name"].lower().replace("-", "_").replace(".", "_")
11-
)
12-
context["__type"] = (
13-
"compiled"
14-
if context["backend"] in ["pybind11", "skbuild", "mesonpy", "maturin"]
15-
else "pure"
16-
)
17-
context["__answers"] = context["_copier_conf"]["answers_file"]
18-
context["__ci"] = "github" if "github.com" in context["url"] else "gitlab"
19-
return {"cookiecutter": context}
71+
return {"cookiecutter": CookiecutterContext(context)}

noxfile.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,7 @@ def nox_session(session: nox.Session, backend: str, vcs: bool) -> None:
325325

326326
@nox.session(default=False)
327327
def compare_copier(session):
328-
# Copier 9.5.0 broke `--data`
329-
# Copier 9.7.0/9.7.1 broke everything
330-
session.install("cookiecutter", "copier!=9.7.*", "copier-templates-extensions")
328+
session.install("cookiecutter", "copier", "copier-templates-extensions")
331329

332330
tmp_dir = session.create_tmp()
333331
session.cd(tmp_dir)

0 commit comments

Comments
 (0)