fix(settings): use <CONFIG_ROOT>/copier as settings directory on Windows (#2071)

Deprecate `<CONFIG_ROOT>/copier/copier` and prefer  `<CONFIG_ROOT>/copier` as the settings directory for consistency across operating systems.
This commit is contained in:
roteiro 2025-04-17 22:05:59 +02:00 committed by GitHub
parent 8f4b0e6620
commit 465a463ec4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 1 deletions

View File

@ -13,6 +13,7 @@ from platformdirs import user_config_path
from pydantic import BaseModel, Field
from .errors import MissingSettingsWarning
from .tools import OS
ENV_VAR = "COPIER_SETTINGS_PATH"
@ -27,6 +28,10 @@ class Settings(BaseModel):
default_factory=set, description="List of trusted repositories or prefixes"
)
@staticmethod
def _default_settings_path() -> Path:
return user_config_path("copier", appauthor=False) / "settings.yml"
@classmethod
def from_file(cls, settings_path: Path | None = None) -> Settings:
"""Load settings from a file."""
@ -35,7 +40,19 @@ class Settings(BaseModel):
if env_path:
settings_path = Path(env_path)
else:
settings_path = user_config_path("copier") / "settings.yml"
settings_path = cls._default_settings_path()
# NOTE: Remove after a sufficiently long deprecation period.
if OS == "windows":
old_settings_path = user_config_path("copier") / "settings.yml"
if old_settings_path.is_file():
warnings.warn(
f"Settings path {old_settings_path} is deprecated. "
f"Please migrate to {settings_path}.",
DeprecationWarning,
stacklevel=2,
)
settings_path = old_settings_path
if settings_path.is_file():
data = yaml.safe_load(settings_path.read_bytes())
return cls.model_validate(data)

View File

@ -10,6 +10,10 @@ standard configuration directory for your platform:
- `%USERPROFILE%\AppData\Local\copier` on Windows as defined in
[Known folders](https://docs.microsoft.com/en-us/windows/win32/shell/known-folders)
!!! note
Windows only: `%USERPROFILE%\AppData\Local\copier\copier` was the standard configuration directory until v9.6.0. This standard configuration directory is deprecated and will be removed in a future version.
This location can be overridden by setting the `COPIER_SETTINGS_PATH` environment
variable.

View File

@ -1,5 +1,7 @@
from __future__ import annotations
import os
import platform
import sys
from pathlib import Path
@ -25,6 +27,18 @@ def test_settings_from_default_location(settings_path: Path) -> None:
assert settings.defaults == {"foo": "bar"}
@pytest.mark.skipif(platform.system() != "Windows", reason="Windows-only test")
def test_default_windows_settings_path() -> None:
settings = Settings()
assert settings._default_settings_path() == Path(
os.getenv("USERPROFILE", default=""),
"AppData",
"Local",
"copier",
"settings.yml",
)
@pytest.mark.usefixtures("config_path")
def test_settings_from_default_location_dont_exists() -> None:
settings = Settings.from_file()