A library for rendering project templates from Git repositories with Jinja2 templating and interactive questionnaires.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advanced copier functionality using the Worker class for fine-grained control over template processing and the Settings class for user configuration management.
The main copier process state manager that provides full control over template operations.
class Worker:
"""Copier process state manager and context manager."""
def __init__(
self,
src_path: str | None = None,
dst_path: Path = Path(),
answers_file: RelativePath | None = None,
vcs_ref: str | VcsRef | None = None,
data: AnyByStrDict = None,
settings: Settings = None,
exclude: Sequence[str] = (),
use_prereleases: bool = False,
skip_if_exists: Sequence[str] = (),
cleanup_on_error: bool = True,
defaults: bool = False,
user_defaults: AnyByStrDict = None,
overwrite: bool = False,
pretend: bool = False,
quiet: bool = False,
conflict: Literal["inline", "rej"] = "inline",
context_lines: PositiveInt = 3,
unsafe: bool = False,
skip_answered: bool = False,
skip_tasks: bool = False
): ...
def run_copy(self) -> None: ...
def run_update(self) -> None: ...
def run_recopy(self) -> None: ...
def __enter__(self) -> Worker: ...
def __exit__(
self,
type: type[BaseException] | None,
value: BaseException | None,
traceback: TracebackType | None
) -> None: ...
# Properties
answers_relpath: Path
all_exclusions: Sequence[str]
jinja_env: YieldEnvironment
match_exclude: Callable[[Path], bool]
match_skip: Callable[[Path], bool]
resolved_vcs_ref: str | None
subproject: Subproject
template: Template
template_copy_root: PathThe Worker class accepts these configuration parameters:
Template and Destination:
src_path (str | None): Template source path (local or Git URL)dst_path (Path): Destination path where to render the subprojectanswers_file (RelativePath | None): Path to answers file relative to dst_pathvcs_ref (str | VcsRef | None): VCS tag/commit/branch to useData and Settings:
data (AnyByStrDict): Answers to the questionnairesettings (Settings): User settings configurationuser_defaults (AnyByStrDict): User default overrides for questionsFile Processing:
exclude (Sequence[str]): File exclusion patternsskip_if_exists (Sequence[str]): File skip patternsuse_prereleases (bool): Consider prereleases when detecting latest versionBehavior Control:
cleanup_on_error (bool): Delete dst_path if there's an errordefaults (bool): Use default answers to questions without promptingoverwrite (bool): Overwrite files that already exist without askingpretend (bool): Produce no real rendering (dry run)quiet (bool): Disable all outputunsafe (bool): Allow usage of unsafe templatesskip_answered (bool): Skip questions that have already been answeredskip_tasks (bool): Skip template tasks executionUpdate/Conflict Resolution:
conflict (Literal["inline", "rej"]): Conflict resolution modecontext_lines (PositiveInt): Lines of context for conflict resolutionUsage examples:
from copier import Worker
# Context manager usage (recommended)
with Worker(
src_path="https://github.com/user/template.git",
dst_path="./my-project",
vcs_ref="v2.0.0",
data={"project_name": "MyApp"},
overwrite=True,
quiet=False
) as worker:
worker.run_copy()
print(f"Generated from: {worker.template}")
# Direct instantiation
worker = Worker(
src_path="./template",
dst_path="./project",
defaults=True,
pretend=True # Dry run
)
result = worker.run_copy()
# Chaining operations
worker = Worker(dst_path="./existing-project")
worker.run_update()
# Later...
worker.run_recopy()User settings configuration for copier defaults and trusted templates.
class Settings:
"""User settings configuration model."""
defaults: dict[str, Any]
trust: set[str]
@classmethod
def from_file(cls, path: StrOrPath | None = None) -> Settings:
"""
Load settings from a YAML file.
Parameters:
- path (StrOrPath, optional): Path to settings file
Returns:
Settings: Loaded settings instance
"""
def is_trusted(self, url: str) -> bool:
"""
Check if a template URL is trusted.
Parameters:
- url (str): Template URL to check
Returns:
bool: True if URL is trusted
"""
def normalize(self) -> dict[str, Any]:
"""
Normalize settings data for serialization.
Returns:
dict: Normalized settings data
"""Settings can be loaded from a YAML file (default location determined by COPIER_SETTINGS_PATH environment variable):
# ~/.config/copier/settings.yml
defaults:
author: "John Doe"
license: "MIT"
python_version: "3.9"
trust:
- "https://github.com/trusted-org/*"
- "https://gitlab.com/my-company/*"Usage examples:
from copier import Settings
import os
# Load from default location
settings = Settings.from_file()
# Load from specific file
settings = Settings.from_file("./copier-settings.yml")
# Check if template is trusted
is_safe = settings.is_trusted("https://github.com/trusted-org/template.git")
# Use settings with Worker
os.environ["COPIER_SETTINGS_PATH"] = "./my-settings.yml"
worker = Worker(
src_path="template/",
dst_path="project/",
# Settings will be automatically loaded
)Working with template metadata and processing details:
from copier import Worker
# Access template information
with Worker("template/", "project/") as worker:
worker.run_copy()
# Template metadata
print(f"Template path: {worker.template.local_abspath}")
print(f"Template ref: {worker.template.ref}")
print(f"Template version: {worker.template.version}")
print(f"Template commit: {worker.template.commit}")
# Processing results
print(f"Answers used: {worker.answers.combined}")
print(f"Destination: {worker.subproject.local_abspath}")
print(f"Answers file: {worker.answers_relpath}")
# Custom conflict resolution
worker = Worker(
src_path="template/",
dst_path="existing-project/",
conflict="rej", # Create .rej files for conflicts
context_lines=5 # Show 5 lines of context
)
worker.run_update()Copier respects several environment variables:
COPIER_SETTINGS_PATH: Path to settings fileGIT_*: Git configuration variablesTMPDIR: Temporary directory for processingimport os
from copier import Worker
# Configure via environment
os.environ["COPIER_SETTINGS_PATH"] = "/custom/settings.yml"
os.environ["TMPDIR"] = "/fast/ssd/tmp"
worker = Worker("template/", "project/")
worker.run_copy()Install with Tessl CLI
npx tessl i tessl/pypi-copier