mirror of
https://github.com/copier-org/copier.git
synced 2025-05-05 23:42:55 +00:00
99 lines
2.8 KiB
Python
99 lines
2.8 KiB
Python
import filecmp
|
|
import json
|
|
import os
|
|
import sys
|
|
import textwrap
|
|
from enum import Enum
|
|
from hashlib import sha1
|
|
from pathlib import Path
|
|
from typing import Dict
|
|
|
|
from plumbum import local
|
|
from prompt_toolkit.input.ansi_escape_sequences import REVERSE_ANSI_SEQUENCES
|
|
from prompt_toolkit.keys import Keys
|
|
|
|
import copier
|
|
from copier.types import StrOrPath
|
|
|
|
PROJECT_TEMPLATE = Path(__file__).parent / "demo"
|
|
|
|
DATA = {
|
|
"py3": True,
|
|
"make_secret": lambda: sha1(os.urandom(48)).hexdigest(),
|
|
"myvar": "awesome",
|
|
"what": "world",
|
|
"project_name": "Copier",
|
|
"version": "2.0.0",
|
|
"description": "A library for rendering projects templates",
|
|
}
|
|
|
|
COPIER_CMD = local.get(
|
|
# Allow debugging in VSCode
|
|
# HACK https://github.com/microsoft/vscode-python/issues/14222
|
|
str(Path(sys.executable).parent / "copier.cmd"),
|
|
str(Path(sys.executable).parent / "copier"),
|
|
# Poetry installs the executable as copier.cmd in Windows
|
|
"copier.cmd",
|
|
"copier",
|
|
)
|
|
COPIER_PATH = str(COPIER_CMD.executable)
|
|
|
|
# Helpers to use with tests designed for old copier bracket envops defaults
|
|
BRACKET_ENVOPS = {
|
|
"autoescape": False,
|
|
"block_end_string": "%]",
|
|
"block_start_string": "[%",
|
|
"comment_end_string": "#]",
|
|
"comment_start_string": "[#",
|
|
"keep_trailing_newline": True,
|
|
"variable_end_string": "]]",
|
|
"variable_start_string": "[[",
|
|
}
|
|
BRACKET_ENVOPS_JSON = json.dumps(BRACKET_ENVOPS)
|
|
SUFFIX_TMPL = ".tmpl"
|
|
|
|
# Helper to parse back an iso-formatted datetime; needed for py3.6, where
|
|
# datetime.datetime.fromisoformat() doesn't exist
|
|
ISOFORMAT = "%Y-%m-%d %H:%M:%S.%f"
|
|
|
|
|
|
class Keyboard(str, Enum):
|
|
ControlH = REVERSE_ANSI_SEQUENCES[Keys.ControlH]
|
|
Enter = "\r"
|
|
Esc = REVERSE_ANSI_SEQUENCES[Keys.Escape]
|
|
|
|
Home = REVERSE_ANSI_SEQUENCES[Keys.Home]
|
|
End = REVERSE_ANSI_SEQUENCES[Keys.End]
|
|
|
|
Up = REVERSE_ANSI_SEQUENCES[Keys.Up]
|
|
Down = REVERSE_ANSI_SEQUENCES[Keys.Down]
|
|
Right = REVERSE_ANSI_SEQUENCES[Keys.Right]
|
|
Left = REVERSE_ANSI_SEQUENCES[Keys.Left]
|
|
|
|
# Equivalent keystrokes in terminals; see python-prompt-toolkit for
|
|
# further explanations
|
|
Alt = Esc
|
|
Backspace = ControlH
|
|
|
|
|
|
def render(tmp_path, **kwargs):
|
|
kwargs.setdefault("quiet", True)
|
|
copier.copy(str(PROJECT_TEMPLATE), tmp_path, data=DATA, **kwargs)
|
|
|
|
|
|
def assert_file(tmp_path, *path):
|
|
p1 = os.path.join(str(tmp_path), *path)
|
|
p2 = os.path.join(str(PROJECT_TEMPLATE), *path)
|
|
assert filecmp.cmp(p1, p2)
|
|
|
|
|
|
def build_file_tree(spec: Dict[StrOrPath, str], dedent: bool = True):
|
|
"""Builds a file tree based on the received spec."""
|
|
for path, contents in spec.items():
|
|
path = Path(path)
|
|
if dedent:
|
|
contents = textwrap.dedent(contents)
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
with path.open("w") as fd:
|
|
fd.write(contents)
|