Commit ca76e11d by Kasper Committed by GitHub

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 <bjorn@neersighted.com>

* Move mypy ignore to `pyproject.toml`

Co-authored-by: Bjorn Neergaard <bjorn@neersighted.com>
parent b2903b83
...@@ -878,6 +878,17 @@ optional = false ...@@ -878,6 +878,17 @@ optional = false
python-versions = "*" python-versions = "*"
[[package]] [[package]]
name = "xattr"
version = "0.9.7"
description = "Python wrapper for extended filesystem attributes"
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
cffi = ">=1.0.0"
[[package]]
name = "zipp" name = "zipp"
version = "3.8.0" version = "3.8.0"
description = "Backport of pathlib-compatible object wrapper for zip files" description = "Backport of pathlib-compatible object wrapper for zip files"
...@@ -1479,6 +1490,12 @@ webencodings = [ ...@@ -1479,6 +1490,12 @@ webencodings = [
{file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"},
{file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"},
] ]
xattr = [
{file = "xattr-0.9.7-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:1b2cd125150aa9bbfb02929627101b3303920a68487e9c865ddd170188ddd796"},
{file = "xattr-0.9.7-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:e2c72a3a501bac715489180ca2b646e48a1ca3a794c1103dd6f0f987d43f570c"},
{file = "xattr-0.9.7-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:1e11ba8ab86dfe74419704c53722ea9b5915833db07416e7c10db5dfb02218bb"},
{file = "xattr-0.9.7.tar.gz", hash = "sha256:b0bbca828e04ef2d484a6522ae7b3a7ccad5e43fa1c6f54d78e24bb870f49d44"},
]
zipp = [ zipp = [
{file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
{file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
......
...@@ -66,6 +66,7 @@ shellingham = "^1.1" ...@@ -66,6 +66,7 @@ shellingham = "^1.1"
tomlkit = ">=0.7.0,<1.0.0" tomlkit = ">=0.7.0,<1.0.0"
# exclude 20.4.5 - 20.4.6 due to https://github.com/pypa/pip/issues/9953 # exclude 20.4.5 - 20.4.6 due to https://github.com/pypa/pip/issues/9953
virtualenv = "(>=20.4.3,<20.4.5 || >=20.4.7)" virtualenv = "(>=20.4.3,<20.4.5 || >=20.4.7)"
xattr = { version = "^0.9.7", markers = "sys_platform == 'darwin'" }
urllib3 = "^1.26.0" urllib3 = "^1.26.0"
dulwich = "^0.20.35" dulwich = "^0.20.35"
...@@ -157,6 +158,7 @@ module = [ ...@@ -157,6 +158,7 @@ module = [
'requests_toolbelt.*', 'requests_toolbelt.*',
'shellingham.*', 'shellingham.*',
'virtualenv.*', 'virtualenv.*',
'xattr.*',
] ]
ignore_missing_imports = true ignore_missing_imports = true
......
...@@ -6,6 +6,7 @@ import itertools ...@@ -6,6 +6,7 @@ import itertools
import json import json
import os import os
import platform import platform
import plistlib
import re import re
import subprocess import subprocess
import sys import sys
...@@ -1087,7 +1088,20 @@ class EnvManager: ...@@ -1087,7 +1088,20 @@ class EnvManager:
args.append(str(path)) args.append(str(path))
return virtualenv.cli_run(args) cli_result = virtualenv.cli_run(args)
# Exclude the venv folder from from macOS Time Machine backups
# TODO: Add backup-ignore markers for other platforms too
if sys.platform == "darwin":
import xattr
xattr.setxattr(
str(path),
"com.apple.metadata:com_apple_backup_excludeItem",
plistlib.dumps("com.apple.backupd", fmt=plistlib.FMT_BINARY),
)
return cli_result
@classmethod @classmethod
def remove_venv(cls, path: Path | str) -> None: def remove_venv(cls, path: Path | str) -> None:
......
...@@ -96,6 +96,27 @@ def test_virtualenvs_with_spaces_in_their_path_work_as_expected( ...@@ -96,6 +96,27 @@ def test_virtualenvs_with_spaces_in_their_path_work_as_expected(
assert venv.run("python", "-V", shell=True).startswith("Python") assert venv.run("python", "-V", shell=True).startswith("Python")
@pytest.mark.skipif(sys.platform != "darwin", reason="requires darwin")
def test_venv_backup_exclusion(tmp_dir: str, manager: EnvManager):
import xattr
venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path))
value = (
b"bplist00_\x10\x11com.apple.backupd"
b"\x08\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00"
b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"
)
assert (
xattr.getxattr(
str(venv_path), "com.apple.metadata:com_apple_backup_excludeItem"
)
== value
)
def test_env_commands_with_spaces_in_their_arg_work_as_expected( def test_env_commands_with_spaces_in_their_arg_work_as_expected(
tmp_dir: str, manager: EnvManager tmp_dir: str, manager: EnvManager
): ):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment