Skip to content

Commit

Permalink
Merge pull request #4 from i-dot-ai/EN-622/nested_templates
Browse files Browse the repository at this point in the history
Add nested templates support
  • Loading branch information
RyanWhite25 authored Oct 15, 2024
2 parents e3a57ee + e9e253e commit 8a48661
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 136 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
fail-fast: false
matrix:
os: ["macos-latest"]
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.11"]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
Expand Down
22 changes: 22 additions & 0 deletions cruft/_commands/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
from typing import Any, Dict, List, Optional

from cookiecutter.generate import generate_files
from cookiecutter.prompt import choose_nested_template

from . import utils
from .utils import example
from .utils.clean import clean_context
from .utils.iohelper import AltTemporaryDirectory
from .utils.nested import get_relative_path, is_nested_template
from .utils.validate import validate_cookiecutter


@example("https://github.com/timothycrosley/cookiecutter-python/")
Expand Down Expand Up @@ -48,6 +51,25 @@ def create(
checkout,
)

if is_nested_template(context):
nested_template = choose_nested_template(
context, cookiecutter_template_dir_str, no_input
)
return create(
template_git_url=template_git_url,
output_dir=output_dir,
config_file=config_file,
default_config=default_config,
extra_context=extra_context,
extra_context_file=extra_context_file,
no_input=no_input,
directory=get_relative_path(nested_template, cookiecutter_template_dir_str),
checkout=checkout,
skip=skip,
)

validate_cookiecutter(cookiecutter_template_dir)

project_dir = Path(
generate_files(
repo_dir=cookiecutter_template_dir,
Expand Down
4 changes: 4 additions & 0 deletions cruft/_commands/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .utils import example
from .utils.clean import clean_context
from .utils.iohelper import AltTemporaryDirectory
from .utils.validate import validate_cookiecutter


@example("https://github.com/timothycrosley/cookiecutter-python/")
Expand Down Expand Up @@ -43,6 +44,9 @@ def link(
project_dir,
checkout,
)

validate_cookiecutter(cookiecutter_template_dir)

if no_input:
use_commit = last_commit
else:
Expand Down
21 changes: 6 additions & 15 deletions cruft/_commands/utils/cookiecutter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from cookiecutter.prompt import prompt_for_config
from git import GitCommandError, Repo

from cruft.exceptions import InvalidCookiecutterRepository, UnableToFindCookiecutterTemplate
from cruft.exceptions import InvalidCookiecutterRepository

from .nested import is_nested_template

CookiecutterContext = Dict[str, Any]

Expand Down Expand Up @@ -62,18 +64,6 @@ def get_cookiecutter_repo(
return repo


def _validate_cookiecutter(cookiecutter_template_dir: Path):
main_cookiecutter_directory: Optional[Path] = None

for dir_item in cookiecutter_template_dir.glob("*cookiecutter.*"):
if dir_item.is_dir() and "{{" in dir_item.name and "}}" in dir_item.name:
main_cookiecutter_directory = dir_item
break

if not main_cookiecutter_directory:
raise UnableToFindCookiecutterTemplate(cookiecutter_template_dir)


def generate_cookiecutter_context(
template_git_url: str,
cookiecutter_template_dir: Path,
Expand All @@ -84,8 +74,6 @@ def generate_cookiecutter_context(
project_dir: Path = Path("."),
checkout: Optional[str] = None,
) -> CookiecutterContext:
_validate_cookiecutter(cookiecutter_template_dir)

context_file = cookiecutter_template_dir / "cookiecutter.json"
config_dict = get_user_config(
config_file=str(config_file) if config_file else None, default_config=default_config
Expand All @@ -97,6 +85,9 @@ def generate_cookiecutter_context(
extra_context=extra_context,
)

if is_nested_template(context):
return context

# prompt the user to manually configure at the command line.
# except when 'no-input' flag is set
context["cookiecutter"] = prompt_for_config(context, no_input)
Expand Down
3 changes: 3 additions & 0 deletions cruft/_commands/utils/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .cookiecutter import CookiecutterContext, generate_cookiecutter_context
from .cruft import CruftState
from .iohelper import AltTemporaryDirectory
from .validate import validate_cookiecutter

if not sys.version_info >= (3, 11):
try:
Expand Down Expand Up @@ -79,6 +80,8 @@ def _generate_output(
no_input=not cookiecutter_input,
)

validate_cookiecutter(inner_dir)

# This generates the cookiecutter template.
# Unfortunately, cookiecutter doesn't let us output the template in an
# arbitrary directory. It insists on creating the initial project directory.
Expand Down
7 changes: 7 additions & 0 deletions cruft/_commands/utils/nested.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def is_nested_template(context):
return bool({"template", "templates"} & set(context["cookiecutter"].keys()))


def get_relative_path(full_path_to_template, temporary_directory_root):
"""Return the path of a nested template relative to the root of a given temporary directory."""
return full_path_to_template.split(temporary_directory_root + "/")[-1]
16 changes: 16 additions & 0 deletions cruft/_commands/utils/validate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pathlib import Path
from typing import Optional

from cruft.exceptions import UnableToFindCookiecutterTemplate


def validate_cookiecutter(cookiecutter_template_dir: Path):
main_cookiecutter_directory: Optional[Path] = None

for dir_item in cookiecutter_template_dir.glob("*cookiecutter.*"):
if dir_item.is_dir() and "{{" in dir_item.name and "}}" in dir_item.name:
main_cookiecutter_directory = dir_item
break

if not main_cookiecutter_directory:
raise UnableToFindCookiecutterTemplate(cookiecutter_template_dir)
Loading

0 comments on commit 8a48661

Please sign in to comment.