{"id":3939,"library":"copier","title":"Copier","description":"Copier is a versatile Python library and CLI tool designed for rendering project templates. It supports both local paths and Git URLs as template sources, allowing for dynamic replacement of values in various text files using Jinja2 templating. It handles project generation and updates, ensuring existing files are not overwritten unless explicitly instructed. The library is actively maintained with frequent updates, providing a robust solution for scaffolding and managing project lifecycles.","status":"active","version":"9.14.3","language":"en","source_language":"en","source_url":"https://github.com/copier-org/copier","tags":["template generation","project scaffolding","cli","jinja2","automation"],"install":[{"cmd":"pip install copier","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Required for using Git repository templates and version control functionality during updates.","package":"Git","optional":false},{"reason":"Used as the templating engine for rendering dynamic content in templates. It is an indirect dependency of `copier`.","package":"Jinja2","optional":false}],"imports":[{"note":"The `copy` function was used in older versions of Copier. As of recent major versions (e.g., Copier 9.x), `run_copy` is the canonical and preferred function for programmatically copying templates, offering explicit parameters instead of `**kwargs`.","wrong":"from copier import copy","symbol":"run_copy","correct":"from copier import run_copy"}],"quickstart":{"code":"import os\nimport shutil\nfrom pathlib import Path\nfrom copier import run_copy\n\n# Define paths for demonstration\ntemplate_path = Path('./my_template')\ndest_path = Path('./my_new_project')\n\n# Clean up previous runs for idempotent quickstart\nif dest_path.exists():\n    shutil.rmtree(dest_path)\nif template_path.exists():\n    shutil.rmtree(template_path)\n\n# 1. Create a dummy template structure\ntemplate_path.mkdir(exist_ok=True)\n(template_path / 'copier.yml').write_text(\n    \"\"\"\n    # questions\n    project_name: \n      type: str\n      help: What is your project name?\n    author_name:\n      type: str\n      default: 'John Doe'\n    \"\"\"\n)\n(template_path / '{{ project_name }}').mkdir()\n(template_path / '{{ project_name }}' / 'README.md.jinja').write_text(\n    \"\"\"\n    # {{ project_name }}\n\n    This project was generated by {{ author_name }}.\n    \"\"\"\n)\n\nprint(f\"Template created at: {template_path.resolve()}\")\n\n# 2. Programmatically copy the template\n# In a real scenario, these answers might be interactively prompted or passed via CLI\nanswers = {\n    'project_name': 'MyAwesomeProject',\n    'author_name': 'AI Assistant'\n}\n\nrun_copy(\n    str(template_path),\n    str(dest_path),\n    data=answers,\n    overwrite=True # Use with caution in real projects\n)\n\nprint(f\"Project generated at: {dest_path.resolve()}\")\nprint(\"Generated README.md content:\")\nprint((dest_path / 'MyAwesomeProject' / 'README.md').read_text())\n\n# Clean up after quickstart\nshutil.rmtree(template_path)\nshutil.rmtree(dest_path)\n","lang":"python","description":"This quickstart demonstrates how to programmatically use `copier.run_copy` to generate a new project from a local template. It first creates a minimal template directory with a `copier.yml` and a Jinja2-templated file, then copies it to a destination, providing answers as a dictionary. The generated project's README content is then printed."},"warnings":[{"fix":"Ensure your environment uses Python 3.10 or a more recent version. Upgrade your Python interpreter if necessary.","message":"Copier 9.x and newer requires Python 3.10 or higher. Older versions supported Python 3.6+.","severity":"breaking","affected_versions":"9.x.x and newer"},{"fix":"Replace all instances of `_copier_conf.json()` in your templates with `_copier_conf|to_json` to correctly render JSON representations of the configuration.","message":"The `_copier_conf.json()` method for accessing configuration data within templates has been removed.","severity":"breaking","affected_versions":"9.14.0 and newer"},{"fix":"To generate separate `.rej` files for conflicts instead of inline markers, use the `--conflict rej` option when running `copier update` or `copier recopy`.","message":"When updating a project, Copier handles merge conflicts by default using 'inline' markers, similar to Git merge conflicts. This can leave `<<<<<<<`, `=======`, `>>>>>>>` markers in your files.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Manually install any additional Python packages required by your template's custom logic into the environment where Copier is running (e.g., `pip install copier my-template-extension`). Consider using `pipx` for isolated Copier installations and then injecting template-specific dependencies into that `pipx` environment.","message":"If your Copier template uses custom Jinja extensions or other Python packages for tasks, these dependencies must be installed in the same Python environment where Copier itself is installed. Copier does not automatically manage template-specific Python dependencies.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Initialize mutable default arguments to `None` and assign the mutable object inside the function if `None` is passed. Example: `def func(arg=None): arg = arg if arg is not None else []`.","message":"When writing custom Python code for Copier templates (e.g., post-copy tasks, custom Jinja extensions), be mindful of mutable default arguments in function definitions. Changes to these mutable defaults (e.g., lists, dictionaries) will persist across multiple calls, leading to unexpected behavior.","severity":"gotcha","affected_versions":"All versions (general Python footgun)"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}