Skip to content

Commit cbdc8ed

Browse files
authored
Remove obsolete extension and clean up replay file extensions (frequenz-floss#118)
The `jinja2_time.TimeExtension` extension was removed in cookiecutter 2.3.0 and both this extension and the new replacement (`cookiecutter.extensions.TimeExtension`) are pre-loaded by cookiecutter, so it wasn't necessary in the first place. We remove it to avoid errors when using the new cookiecutter version. new version. Also we now remove the `_extensions` key from the generated replay file for new projects as it is only likely to create more upgrade errors, and we almost always want to just use the extensions declared by the template itself, not our own.
2 parents a7c7520 + 4ed4bdb commit cbdc8ed

File tree

8 files changed

+117
-127
lines changed

8 files changed

+117
-127
lines changed

RELEASE_NOTES.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
### Cookiecutter template
1212

13-
<!-- Here upgrade steps for cookiecutter specifically -->
13+
- If your replay file contains a `_extensions` key, you should remove it, as you most likely want to use the extensions declared by the repo-config cookiecutter template you are upgrading to, otherwise you could get errors about missing extensions.
14+
15+
- If your replay file contains a long `Introduction` key, you can replace it with an empty string (`""`), it doesn't need to have any particular content and it increases the size and noise in the replay file.
1416

1517
## New Features
1618

@@ -25,6 +27,20 @@
2527

2628
This makes it easier to upgrade projects to new templates, as removing whole lines is easier than having to edit them.
2729

30+
- Clean up `_extensions` from the generated replay file.
31+
32+
It is not needed in the generated project, we always want to use the ones from the repo-config template.
33+
34+
This should ease upgrading projects, making it less likely to have errors about missing extensions.
35+
36+
- Clean up the `Introduction` variable from the generated replay file.
37+
38+
This is just a hack to be able to show a help about the template variables, keeping that text only increases the size and noise in the replay file.
39+
40+
- Add a `\n` to the end of the replay file.
41+
42+
This is just to be nice to most editors and text files conventions, that likes it more if there is a `\n` at the end of the file.
43+
2844
## Bug Fixes
2945

3046
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->

cookiecutter/cookiecutter.json

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
11
{
2-
"Introduction": "{{cookiecutter | introduction}}",
3-
"type": [
4-
"actor",
5-
"api",
6-
"app",
7-
"lib",
8-
"model"
9-
],
10-
"name": null,
11-
"description": null,
12-
"title": "{{cookiecutter | title}}",
13-
"keywords": "(comma separated: 'frequenz', <type> and <name> are included automatically)",
14-
"github_org": "frequenz-floss",
15-
"license": [
16-
"MIT",
17-
"Proprietary"
18-
],
19-
"author_name": "Frequenz Energy-as-a-Service GmbH",
20-
"author_email": "[email protected]",
21-
"python_package": "{{cookiecutter | python_package}}",
22-
"pypi_package_name": "{{cookiecutter | pypi_package_name}}",
23-
"github_repo_name": "{{cookiecutter | github_repo_name}}",
24-
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)",
25-
"_extensions": [
26-
"jinja2_time.TimeExtension",
27-
"local_extensions.as_identifier",
28-
"local_extensions.default_codeowners",
29-
"local_extensions.github_repo_name",
30-
"local_extensions.introduction",
31-
"local_extensions.keywords",
32-
"local_extensions.pypi_package_name",
33-
"local_extensions.python_package",
34-
"local_extensions.src_path",
35-
"local_extensions.title"
36-
]
2+
"Introduction": "{{cookiecutter | introduction}}",
3+
"type": [
4+
"actor",
5+
"api",
6+
"app",
7+
"lib",
8+
"model"
9+
],
10+
"name": null,
11+
"description": null,
12+
"title": "{{cookiecutter | title}}",
13+
"keywords": "(comma separated: 'frequenz', <type> and <name> are included automatically)",
14+
"github_org": "frequenz-floss",
15+
"license": [
16+
"MIT",
17+
"Proprietary"
18+
],
19+
"author_name": "Frequenz Energy-as-a-Service GmbH",
20+
"author_email": "[email protected]",
21+
"python_package": "{{cookiecutter | python_package}}",
22+
"pypi_package_name": "{{cookiecutter | pypi_package_name}}",
23+
"github_repo_name": "{{cookiecutter | github_repo_name}}",
24+
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)",
25+
"_extensions": [
26+
"local_extensions.as_identifier",
27+
"local_extensions.default_codeowners",
28+
"local_extensions.github_repo_name",
29+
"local_extensions.introduction",
30+
"local_extensions.keywords",
31+
"local_extensions.pypi_package_name",
32+
"local_extensions.python_package",
33+
"local_extensions.src_path",
34+
"local_extensions.title"
35+
]
3736
}

cookiecutter/hooks/post_gen_project.py

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,53 @@ def finish_setup() -> None:
131131
commit_git_changes(first_commit=was_repo_initialized)
132132

133133

134+
def clean_replay_file(
135+
*,
136+
replay_data: dict[str, Any],
137+
src: _pathlib.Path, # pylint: disable=unused-argument
138+
dst: _pathlib.Path,
139+
) -> dict[str, Any]:
140+
"""Clean the replay file.
141+
142+
Performs some cleaning of the replay file generated by cookiecutter to make it
143+
more suitable for the generated project.
144+
145+
Args:
146+
replay_data: The replay data to clean.
147+
src: The path of the original replay file.
148+
dst: The path of the cleaned replay file.
149+
150+
Returns:
151+
The cleaned replay data.
152+
"""
153+
# Remove the _output_dir key from the replay data because it is an absolute path
154+
# that depends on the current environment and we don't want to add it as part of
155+
# the generated project.
156+
replay_data["cookiecutter"].pop("_output_dir", None)
157+
158+
# Remove the _extensions key from the replay data because it is not needed in the
159+
# generated project, we always want to use the ones from the repo-config template.
160+
# This should ease upgrading.
161+
replay_data["cookiecutter"].pop("_extensions", None)
162+
163+
# Overwrite the Introduction (which contains just a long description of the
164+
# cookiecutter variables) with an empty string to reduce the replay file size and
165+
# avoid noise.
166+
replay_data["cookiecutter"]["Introduction"] = ""
167+
168+
if template := replay_data["cookiecutter"].get("_template"):
169+
if not template.startswith(("gh:", "git@", "https://")):
170+
print(
171+
f"WARNING: The replay file's `_template` ({template}) doesn't seem "
172+
"to be a remote repository, it won't be saved to avoid storing a "
173+
"local template in the new repository. If this is incorrect, "
174+
f"please add it back manually to {dst}."
175+
)
176+
replay_data["cookiecutter"].pop("_template", None)
177+
178+
return replay_data
179+
180+
134181
def copy_replay_file() -> None:
135182
"""Copy the replay file to the project root."""
136183
src = _pathlib.Path("~/.cookiecutter_replay/cookiecutter.json").expanduser()
@@ -146,25 +193,13 @@ def copy_replay_file() -> None:
146193

147194
try:
148195
with src.open("r", encoding="utf8") as input_file:
149-
replay_data = _json.load(input_file)
150-
151-
# Remove the _output_dir key from the replay data because it is an absolute path
152-
# that depends on the current environment and we don't want to add it as part of
153-
# the generated project.
154-
replay_data["cookiecutter"].pop("_output_dir", None)
155-
156-
if template := replay_data["cookiecutter"].get("_template"):
157-
if not template.startswith(("gh:", "git@", "https://")):
158-
print(
159-
f"WARNING: The replay file's `_template` ({template}) doesn't seem "
160-
"to be a remote repository, it won't be saved to avoid storing a "
161-
"local template in the new repository. If this is incorrect, "
162-
f"please add it back manually to {dst}."
163-
)
164-
replay_data["cookiecutter"].pop("_template", None)
196+
replay_data = clean_replay_file(
197+
replay_data=_json.load(input_file), src=src, dst=dst
198+
)
165199

166200
with dst.open("w", encoding="utf8") as output_file:
167201
_json.dump(replay_data, output_file, indent=2)
202+
output_file.write("\n")
168203
except KeyError as error:
169204
print(
170205
f"WARNING: Error parsing the replay file {src} -> {dst} ({error}). "
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"cookiecutter": {
3-
"Introduction": "]\n\nWelcome to repo-config Cookiecutter template!\n\nThis template will help you to create a new repository for your project. You will be asked to provide some information about your project.\n\nHere is an explanation of what each variable is for and will be used for:\n\n* `type`: The type of repository. It must be chosen from the list.\n\n* `name`: The name of the project. This will be used to build defaults for\n other inputs, such as `title`, `python_package`, etc. It should be one word,\n using only alphanumeric characters (and starting with a letter). It can\n include also `_` and `-` which will be handled differently when building\n other variables from it (replaced by spaces in titles for example).\n\n* `description`: A short description of the project. It will be used as the\n description in the `README.md`, `pyproject.toml`, `mkdocs.yml`, etc.\n\n* `title`: A human-readable name or title for the project. It will be used in\n the `README.md`, `CONTRIBUTING.md`, and other files to refer to the project,\n as well as the site title in `mkdocs.yml`.\n\n* `keywords`: A comma-separated list of keywords that will be used in the\n `pyproject.toml` file. If left untouched, it will use only some predefined\n keywords. If anything else is entered, it will be **added** to the default\n keywords.\n\n* `github_org`: The GitHub handle of the organization where the project will\n reside. This will be used to generate links to the project on GitHub.\n\n* `license`: Currently, only two options are provided: `MIT`, which should be\n used for open-source projects, and `Proprietary`, which should be used for\n closed-source projects. This will be added to file headers and used as the\n license in `pyproject.toml`.\n\n* `author_name`, `author_email`: The name and email address of the author of\n the project. They will be used in the copyright notice in file headers and\n as the author in `pyproject.toml`.\n\n* `python_package`: The Python package in which this project will reside. All\n files provided by this project should be located in this package. This needs\n to be a list of valid Python identifiers separated by dots. The source file\n structure will be derived from this. For example, `frequenz.actor.example`\n will generate files in `src/frequenz/actor/example`.\n\n* `pypi_package_name`: The name of the PyPI/wheel/distribution package. This\n should be consistent with the `python_package`, usually replacing `.` with\n `-`. For example, `frequenz-actor-example`.\n\n* `github_repo_name`: The handle of the GitHub repository where the project\n will reside. This will be used to generate links to the project on GitHub and\n as the top-level directory name.\n\n* `default_codeowners`: A space-separated list of GitHub teams (`@org/team`) or\n users (`@user`) that will be the default code owners for this project. This\n will be used to build the `CODEOWNERS` file. Please refer to the [code owners\n documentation] for more details on the valid syntax.\n\n[code owners documentation]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n\n[Please press any key to continue",
3+
"Introduction": "",
44
"type": "actor",
55
"name": "test",
66
"description": "Test description",
@@ -13,18 +13,6 @@
1313
"python_package": "frequenz.actor.test",
1414
"pypi_package_name": "frequenz-actor-test",
1515
"github_repo_name": "frequenz-actor-test",
16-
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)",
17-
"_extensions": [
18-
"jinja2_time.TimeExtension",
19-
"local_extensions.as_identifier",
20-
"local_extensions.default_codeowners",
21-
"local_extensions.github_repo_name",
22-
"local_extensions.introduction",
23-
"local_extensions.keywords",
24-
"local_extensions.pypi_package_name",
25-
"local_extensions.python_package",
26-
"local_extensions.src_path",
27-
"local_extensions.title"
28-
]
16+
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)"
2917
}
30-
}
18+
}
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"cookiecutter": {
3-
"Introduction": "]\n\nWelcome to repo-config Cookiecutter template!\n\nThis template will help you to create a new repository for your project. You will be asked to provide some information about your project.\n\nHere is an explanation of what each variable is for and will be used for:\n\n* `type`: The type of repository. It must be chosen from the list.\n\n* `name`: The name of the project. This will be used to build defaults for\n other inputs, such as `title`, `python_package`, etc. It should be one word,\n using only alphanumeric characters (and starting with a letter). It can\n include also `_` and `-` which will be handled differently when building\n other variables from it (replaced by spaces in titles for example).\n\n* `description`: A short description of the project. It will be used as the\n description in the `README.md`, `pyproject.toml`, `mkdocs.yml`, etc.\n\n* `title`: A human-readable name or title for the project. It will be used in\n the `README.md`, `CONTRIBUTING.md`, and other files to refer to the project,\n as well as the site title in `mkdocs.yml`.\n\n* `keywords`: A comma-separated list of keywords that will be used in the\n `pyproject.toml` file. If left untouched, it will use only some predefined\n keywords. If anything else is entered, it will be **added** to the default\n keywords.\n\n* `github_org`: The GitHub handle of the organization where the project will\n reside. This will be used to generate links to the project on GitHub.\n\n* `license`: Currently, only two options are provided: `MIT`, which should be\n used for open-source projects, and `Proprietary`, which should be used for\n closed-source projects. This will be added to file headers and used as the\n license in `pyproject.toml`.\n\n* `author_name`, `author_email`: The name and email address of the author of\n the project. They will be used in the copyright notice in file headers and\n as the author in `pyproject.toml`.\n\n* `python_package`: The Python package in which this project will reside. All\n files provided by this project should be located in this package. This needs\n to be a list of valid Python identifiers separated by dots. The source file\n structure will be derived from this. For example, `frequenz.actor.example`\n will generate files in `src/frequenz/actor/example`.\n\n* `pypi_package_name`: The name of the PyPI/wheel/distribution package. This\n should be consistent with the `python_package`, usually replacing `.` with\n `-`. For example, `frequenz-actor-example`.\n\n* `github_repo_name`: The handle of the GitHub repository where the project\n will reside. This will be used to generate links to the project on GitHub and\n as the top-level directory name.\n\n* `default_codeowners`: A space-separated list of GitHub teams (`@org/team`) or\n users (`@user`) that will be the default code owners for this project. This\n will be used to build the `CODEOWNERS` file. Please refer to the [code owners\n documentation] for more details on the valid syntax.\n\n[code owners documentation]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n\n[Please press any key to continue",
3+
"Introduction": "",
44
"type": "api",
55
"name": "test",
66
"description": "Test description",
@@ -13,18 +13,6 @@
1313
"python_package": "frequenz.api.test",
1414
"pypi_package_name": "frequenz-api-test",
1515
"github_repo_name": "frequenz-api-test",
16-
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)",
17-
"_extensions": [
18-
"jinja2_time.TimeExtension",
19-
"local_extensions.as_identifier",
20-
"local_extensions.default_codeowners",
21-
"local_extensions.github_repo_name",
22-
"local_extensions.introduction",
23-
"local_extensions.keywords",
24-
"local_extensions.pypi_package_name",
25-
"local_extensions.python_package",
26-
"local_extensions.src_path",
27-
"local_extensions.title"
28-
]
16+
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)"
2917
}
30-
}
18+
}
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"cookiecutter": {
3-
"Introduction": "]\n\nWelcome to repo-config Cookiecutter template!\n\nThis template will help you to create a new repository for your project. You will be asked to provide some information about your project.\n\nHere is an explanation of what each variable is for and will be used for:\n\n* `type`: The type of repository. It must be chosen from the list.\n\n* `name`: The name of the project. This will be used to build defaults for\n other inputs, such as `title`, `python_package`, etc. It should be one word,\n using only alphanumeric characters (and starting with a letter). It can\n include also `_` and `-` which will be handled differently when building\n other variables from it (replaced by spaces in titles for example).\n\n* `description`: A short description of the project. It will be used as the\n description in the `README.md`, `pyproject.toml`, `mkdocs.yml`, etc.\n\n* `title`: A human-readable name or title for the project. It will be used in\n the `README.md`, `CONTRIBUTING.md`, and other files to refer to the project,\n as well as the site title in `mkdocs.yml`.\n\n* `keywords`: A comma-separated list of keywords that will be used in the\n `pyproject.toml` file. If left untouched, it will use only some predefined\n keywords. If anything else is entered, it will be **added** to the default\n keywords.\n\n* `github_org`: The GitHub handle of the organization where the project will\n reside. This will be used to generate links to the project on GitHub.\n\n* `license`: Currently, only two options are provided: `MIT`, which should be\n used for open-source projects, and `Proprietary`, which should be used for\n closed-source projects. This will be added to file headers and used as the\n license in `pyproject.toml`.\n\n* `author_name`, `author_email`: The name and email address of the author of\n the project. They will be used in the copyright notice in file headers and\n as the author in `pyproject.toml`.\n\n* `python_package`: The Python package in which this project will reside. All\n files provided by this project should be located in this package. This needs\n to be a list of valid Python identifiers separated by dots. The source file\n structure will be derived from this. For example, `frequenz.actor.example`\n will generate files in `src/frequenz/actor/example`.\n\n* `pypi_package_name`: The name of the PyPI/wheel/distribution package. This\n should be consistent with the `python_package`, usually replacing `.` with\n `-`. For example, `frequenz-actor-example`.\n\n* `github_repo_name`: The handle of the GitHub repository where the project\n will reside. This will be used to generate links to the project on GitHub and\n as the top-level directory name.\n\n* `default_codeowners`: A space-separated list of GitHub teams (`@org/team`) or\n users (`@user`) that will be the default code owners for this project. This\n will be used to build the `CODEOWNERS` file. Please refer to the [code owners\n documentation] for more details on the valid syntax.\n\n[code owners documentation]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n\n[Please press any key to continue",
3+
"Introduction": "",
44
"type": "app",
55
"name": "test",
66
"description": "Test description",
@@ -13,18 +13,6 @@
1313
"python_package": "frequenz.app.test",
1414
"pypi_package_name": "frequenz-app-test",
1515
"github_repo_name": "frequenz-app-test",
16-
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)",
17-
"_extensions": [
18-
"jinja2_time.TimeExtension",
19-
"local_extensions.as_identifier",
20-
"local_extensions.default_codeowners",
21-
"local_extensions.github_repo_name",
22-
"local_extensions.introduction",
23-
"local_extensions.keywords",
24-
"local_extensions.pypi_package_name",
25-
"local_extensions.python_package",
26-
"local_extensions.src_path",
27-
"local_extensions.title"
28-
]
16+
"default_codeowners": "(like @some-org/some-team; defaults to a team based on the repo type)"
2917
}
30-
}
18+
}

0 commit comments

Comments
 (0)