Skip to content

Commit ca76e11

Browse files
Exclude .venv from Time Machine backups (#4599)
* Exclude .venv from Time Machine backups * Remove leftover print statements * Make backup exclusion test only run on darwin * Add comment explaining backup exclusion xattr value * Use plistlib to generate backup exclusion xattr value * Only install xattr on darwin * Add TODO comment * Merge fix * Only import xattr on macOS test * Try fixing CI error * Add type annotations * Fix CI errors * Add spacing pyproject.toml Co-authored-by: Bjorn Neergaard <[email protected]> * Move mypy ignore to `pyproject.toml` Co-authored-by: Bjorn Neergaard <[email protected]>
1 parent b2903b8 commit ca76e11

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

poetry.lock

+17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ shellingham = "^1.1"
6666
tomlkit = ">=0.7.0,<1.0.0"
6767
# exclude 20.4.5 - 20.4.6 due to https://github.com/pypa/pip/issues/9953
6868
virtualenv = "(>=20.4.3,<20.4.5 || >=20.4.7)"
69+
xattr = { version = "^0.9.7", markers = "sys_platform == 'darwin'" }
6970
urllib3 = "^1.26.0"
7071
dulwich = "^0.20.35"
7172

@@ -157,6 +158,7 @@ module = [
157158
'requests_toolbelt.*',
158159
'shellingham.*',
159160
'virtualenv.*',
161+
'xattr.*',
160162
]
161163
ignore_missing_imports = true
162164

src/poetry/utils/env.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import json
77
import os
88
import platform
9+
import plistlib
910
import re
1011
import subprocess
1112
import sys
@@ -1087,7 +1088,20 @@ def build_venv(
10871088

10881089
args.append(str(path))
10891090

1090-
return virtualenv.cli_run(args)
1091+
cli_result = virtualenv.cli_run(args)
1092+
1093+
# Exclude the venv folder from from macOS Time Machine backups
1094+
# TODO: Add backup-ignore markers for other platforms too
1095+
if sys.platform == "darwin":
1096+
import xattr
1097+
1098+
xattr.setxattr(
1099+
str(path),
1100+
"com.apple.metadata:com_apple_backup_excludeItem",
1101+
plistlib.dumps("com.apple.backupd", fmt=plistlib.FMT_BINARY),
1102+
)
1103+
1104+
return cli_result
10911105

10921106
@classmethod
10931107
def remove_venv(cls, path: Path | str) -> None:

tests/utils/test_env.py

+21
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,27 @@ def test_virtualenvs_with_spaces_in_their_path_work_as_expected(
9696
assert venv.run("python", "-V", shell=True).startswith("Python")
9797

9898

99+
@pytest.mark.skipif(sys.platform != "darwin", reason="requires darwin")
100+
def test_venv_backup_exclusion(tmp_dir: str, manager: EnvManager):
101+
import xattr
102+
103+
venv_path = Path(tmp_dir) / "Virtual Env"
104+
105+
manager.build_venv(str(venv_path))
106+
107+
value = (
108+
b"bplist00_\x10\x11com.apple.backupd"
109+
b"\x08\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00"
110+
b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"
111+
)
112+
assert (
113+
xattr.getxattr(
114+
str(venv_path), "com.apple.metadata:com_apple_backup_excludeItem"
115+
)
116+
== value
117+
)
118+
119+
99120
def test_env_commands_with_spaces_in_their_arg_work_as_expected(
100121
tmp_dir: str, manager: EnvManager
101122
):

0 commit comments

Comments
 (0)