A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Support for Git repositories, zip files, and URL-based templates with automatic cloning, extraction, and local caching. This module enables cookiecutter to work with templates from various sources including local directories, remote Git repositories, and zip archives.
Determine repository type and locate template directories from various sources.
def determine_repo_dir(
template,
abbreviations,
clone_to_dir,
checkout,
no_input,
password=None,
directory=None
):
"""
Locate repository directory from template reference.
Parameters:
- template: str - Template path, URL, or abbreviation
- abbreviations: dict - Repository abbreviations (e.g., 'gh' -> GitHub URL)
- clone_to_dir: str - Directory to clone repositories into
- checkout: str, optional - Branch, tag, or commit to checkout
- no_input: bool - Whether to prompt user for input
- password: str, optional - Password for protected repositories
- directory: str, optional - Subdirectory within repository containing template
Returns:
tuple - (repo_directory_path, should_cleanup_bool)
"""
def repository_has_cookiecutter_json(repo_directory):
"""
Check if directory contains cookiecutter.json.
Parameters:
- repo_directory: str - Directory path to check
Returns:
bool - True if cookiecutter.json exists in directory
"""Analyze template references to determine their type and format.
def is_repo_url(value):
"""
Check if value is a repository URL.
Parameters:
- value: str - Value to check
Returns:
bool - True if value appears to be a repository URL
"""
def is_zip_file(value):
"""
Check if value is a zip file.
Parameters:
- value: str - Value to check (file path or URL)
Returns:
bool - True if value appears to be a zip file
"""
def expand_abbreviations(template, abbreviations):
"""
Expand template name abbreviations.
Parameters:
- template: str - Template reference (may contain abbreviation)
- abbreviations: dict - Abbreviation mapping (e.g., 'gh' -> GitHub URL pattern)
Returns:
str - Expanded template URL or original template if no abbreviation
"""Clone repositories using Git or Mercurial.
def clone(repo_url, checkout=None, clone_to_dir=".", no_input=False):
"""
Clone repository to directory.
Parameters:
- repo_url: str - Repository URL to clone
- checkout: str, optional - Branch, tag, or commit to checkout after clone
- clone_to_dir: str - Directory to clone into
- no_input: bool - Whether to prompt for user input on conflicts
Returns:
str - Path to cloned repository directory
"""
def identify_repo(repo_url):
"""
Determine if repo URL is git or hg.
Parameters:
- repo_url: str - Repository URL
Returns:
str - Repository type ('git' or 'hg')
"""
def is_vcs_installed(repo_type):
"""
Check if VCS is installed.
Parameters:
- repo_type: str - Version control system type ('git' or 'hg')
Returns:
bool - True if VCS is available on the system
"""Download and extract zip archives containing templates.
def unzip(zip_uri, is_url, clone_to_dir=".", no_input=False, password=None):
"""
Download and unpack zipfile from URI.
Parameters:
- zip_uri: str - URI to zip file (local path or URL)
- is_url: bool - Whether zip_uri is a URL or local path
- clone_to_dir: str - Directory to extract zip contents
- no_input: bool - Whether to prompt for user input
- password: str, optional - Password for protected zip files
Returns:
str - Path to extracted directory
"""REPO_REGEX: Pattern # Regex pattern for matching repository URLs
BRANCH_ERRORS: list # List of branch-related error strings for VCS operationsfrom cookiecutter.repository import determine_repo_dir, clone
from cookiecutter.config import get_user_config
# Get user configuration for abbreviations
config = get_user_config()
# Determine repository directory from GitHub URL
repo_dir, cleanup = determine_repo_dir(
template='https://github.com/audreyfeldroy/cookiecutter-pypackage.git',
abbreviations=config['abbreviations'],
clone_to_dir=config['cookiecutters_dir'],
checkout='master',
no_input=True
)
# Direct cloning
cloned_path = clone(
repo_url='https://github.com/user/template-repo.git',
checkout='v2.0.0',
clone_to_dir='./templates'
)from cookiecutter.repository import expand_abbreviations, determine_repo_dir
from cookiecutter.config import BUILTIN_ABBREVIATIONS
# Expand GitHub abbreviation
full_url = expand_abbreviations(
'gh:audreyfeldroy/cookiecutter-pypackage',
BUILTIN_ABBREVIATIONS
)
# Returns: 'https://github.com/audreyfeldroy/cookiecutter-pypackage.git'
# Use with custom abbreviations
custom_abbrevs = {
'gh': 'https://github.com/{}.git',
'company': 'https://git.company.com/{}.git'
}
company_url = expand_abbreviations(
'company:internal/python-template',
custom_abbrevs
)
# Returns: 'https://git.company.com/internal/python-template.git'from cookiecutter.repository import unzip, is_zip_file
# Check if source is a zip file
template_source = 'https://github.com/user/template/archive/master.zip'
if is_zip_file(template_source):
# Extract zip file
extracted_path = unzip(
zip_uri=template_source,
is_url=True,
clone_to_dir='./templates',
password=None
)
print(f"Template extracted to: {extracted_path}")
# Local zip file
local_zip = './my-template.zip'
if is_zip_file(local_zip):
extracted_path = unzip(
zip_uri=local_zip,
is_url=False,
clone_to_dir='./templates'
)from cookiecutter.repository import (
repository_has_cookiecutter_json,
is_repo_url,
is_vcs_installed
)
# Validate repository structure
repo_path = './downloaded-template'
if repository_has_cookiecutter_json(repo_path):
print("Valid cookiecutter template found")
else:
print("No cookiecutter.json found in repository")
# Check URL format
template_ref = 'https://github.com/user/repo.git'
if is_repo_url(template_ref):
print("Template reference is a repository URL")
# Verify VCS availability
if is_vcs_installed('git'):
print("Git is available for cloning repositories")
else:
print("Git not found - cannot clone repositories")from cookiecutter.repository import determine_repo_dir, identify_repo
from cookiecutter.exceptions import RepositoryNotFound, RepositoryCloneFailed
try:
# Handle different repository types
template_sources = [
'gh:audreyfeldroy/cookiecutter-pypackage', # GitHub abbreviation
'https://bitbucket.org/user/template.git', # Bitbucket Git
'https://gitlab.com/user/template.git', # GitLab Git
'./local-template/', # Local directory
'https://example.com/template.zip' # Zip file URL
]
config = get_user_config()
for template in template_sources:
try:
# Determine repository type and get directory
repo_dir, should_cleanup = determine_repo_dir(
template=template,
abbreviations=config['abbreviations'],
clone_to_dir=config['cookiecutters_dir'],
checkout=None,
no_input=True,
directory='subdirectory' # Look for template in subdirectory
)
print(f"Template ready at: {repo_dir}")
# Use the template...
# Cleanup if needed
if should_cleanup:
import shutil
shutil.rmtree(repo_dir)
except RepositoryNotFound:
print(f"Repository not found: {template}")
except RepositoryCloneFailed:
print(f"Failed to clone repository: {template}")
except Exception as e:
print(f"Repository handling error: {e}")from cookiecutter.repository import clone, identify_repo
# Clone specific branch or tag
branches_to_try = ['main', 'master', 'develop', 'v2.0.0']
for branch in branches_to_try:
try:
repo_path = clone(
repo_url='https://github.com/user/template.git',
checkout=branch,
clone_to_dir='./templates',
no_input=True
)
print(f"Successfully cloned branch/tag: {branch}")
break
except Exception:
print(f"Failed to clone {branch}, trying next...")
continueInstall with Tessl CLI
npx tessl i tessl/pypi-cookiecutter