Skip to content

Commit ce17181

Browse files
Add lazy version of shared_datadir (#107)
Co-authored-by: Bruno Oliveira <[email protected]>
1 parent 2a63b82 commit ce17181

File tree

4 files changed

+85
-0
lines changed

4 files changed

+85
-0
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ UNRELEASED
66

77
*UNRELEASED*
88

9+
- New ``lazy_shared_datadir`` fixture, which brings the same lazy functionality as ``lazy_datadir`` for the *shared* directory.
910
- Fix ``LazyDataDir.joinpath`` typing to also support ``Path`` objects as the right-hand side parameter.
1011

1112
1.7.2

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ def test_read_module(lazy_datadir):
5656

5757
Unlike `datadir`, `lazy_datadir` is an object that only implements `joinpath` and `/` operations. While not fully backward-compatible with `datadir`, most tests can switch to `lazy_datadir` without modifications.
5858

59+
### lazy_shared_datadir
60+
61+
`lazy_shared_datadir` is similar to `lazy_datadir`, but applied to the shared data directory `shared_datadir`.
62+
That is, instead of copying all files in `shared_datadir`, files are only copied as necessary when accessed via `joinpath` or the `/` operator.
63+
This allows for a shared data directory to be pulled from lazily in the same manner as `lazy_datadir`.
64+
65+
```python
66+
def test_read_global(lazy_shared_datadir):
67+
contents = (lazy_shared_datadir / "hello.txt").read_text()
68+
assert contents == "Hello World!\n"
69+
```
70+
5971
# License
6072

6173
MIT.

src/pytest_datadir/plugin.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,24 @@ def lazy_datadir(original_datadir: Path, tmp_path: Path) -> LazyDataDir:
115115
tmp_path: Pytest's built-in fixture providing a temporary directory path.
116116
"""
117117
return LazyDataDir(original_datadir, tmp_path)
118+
119+
120+
@pytest.fixture
121+
def lazy_shared_datadir(request: pytest.FixtureRequest, tmp_path: Path) -> LazyDataDir:
122+
"""
123+
Return a lazy version of the shared data directory.
124+
125+
Here, "lazy" means that the temporary directory is initially created empty.
126+
127+
Files and directories are then copied from the data directory only when first
128+
accessed via the ``joinpath`` method or the ``/`` operator.
129+
130+
Args:
131+
request: The Pytest fixture request object.
132+
tmp_path: Pytest's built-in fixture providing a temporary directory path.
133+
"""
134+
original_shared_path = Path(os.path.join(request.fspath.dirname, "data"))
135+
temp_path = tmp_path / "data"
136+
temp_path.mkdir(parents=True, exist_ok=False)
137+
138+
return LazyDataDir(original_shared_path, temp_path)

tests/test_hello.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,54 @@ def test_lazy_copy_sub_directory(lazy_datadir: LazyDataDir) -> None:
140140
"local_directory",
141141
}
142142
assert fn.read_text() == "local contents"
143+
144+
145+
def test_shared_lazy_copy(lazy_shared_datadir: LazyDataDir, tmp_path: Path) -> None:
146+
# The temporary directory starts containing only an empty data directory.
147+
assert {x.name for x in tmp_path.iterdir()} == {"data"}
148+
assert {x.name for x in lazy_shared_datadir.tmp_path.iterdir()} == set()
149+
150+
# Lazy copy file.
151+
spam = lazy_shared_datadir / "spam.txt"
152+
assert {x.name for x in lazy_shared_datadir.tmp_path.iterdir()} == {"spam.txt"}
153+
assert spam.read_text() == "eggs\n"
154+
155+
# Accessing the same file multiple times does not copy the file again.
156+
spam.write_text("eggs and ham\n")
157+
spam = lazy_shared_datadir / Path("spam.txt")
158+
assert spam.read_text() == "eggs and ham\n"
159+
160+
# Lazy copy data directory.
161+
shared_dir = lazy_shared_datadir / "shared_directory"
162+
assert {x.name for x in lazy_shared_datadir.tmp_path.iterdir()} == {
163+
"spam.txt",
164+
"shared_directory",
165+
}
166+
assert shared_dir.is_dir() is True
167+
assert shared_dir.joinpath("file.txt").read_text() == "global contents"
168+
169+
# It is OK to request a file that does not exist in the data directory.
170+
fn = lazy_shared_datadir / "new-file.txt"
171+
assert fn.exists() is False
172+
fn.write_text("new contents")
173+
assert {x.name for x in lazy_shared_datadir.tmp_path.iterdir()} == {
174+
"spam.txt",
175+
"shared_directory",
176+
"new-file.txt",
177+
}
178+
179+
180+
def test_shared_lazy_copy_sub_directory(
181+
lazy_shared_datadir: LazyDataDir, tmp_path: Path
182+
) -> None:
183+
"""Copy via file by using a sub-directory (#99)."""
184+
# The temporary directory starts containing only an empty data directory.
185+
assert {x.name for x in tmp_path.iterdir()} == {"data"}
186+
assert {x.name for x in lazy_shared_datadir.tmp_path.iterdir()} == set()
187+
188+
# Lazy copy file in a sub-directory.
189+
fn = lazy_shared_datadir / "shared_directory/file.txt"
190+
assert {x.name for x in lazy_shared_datadir.tmp_path.iterdir()} == {
191+
"shared_directory",
192+
}
193+
assert fn.read_text() == "global contents"

0 commit comments

Comments
 (0)