Skip to content

Commit a67f622

Browse files
authored
ci: add windows to test matrix (#149)
* ci: add windows to test matrix * ci: explicitly use bash shell * ci: do not use pytest-parallel on windows * tests: path tests now windows compatible * fix(rsconnect): possible race condition in bundle creation * tests: add time delay to cache tests for windows * tests: try increasing time delay
1 parent c8b5cb7 commit a67f622

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

.github/workflows/ci.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
matrix:
2323
python: ["3.7", "3.8", "3.9", "3.10"]
2424
os: ["ubuntu-latest"]
25-
pytest_ops: [""]
25+
pytest_opts: ["--workers 4 --tests-per-worker 1"]
2626
requirements: [""]
2727
include:
2828
- os: "ubuntu-latest"
@@ -32,13 +32,18 @@ jobs:
3232
python: "3.10"
3333
# ignore doctests, as they involve calls to github, and all mac machines
3434
# use the same IP address
35+
pytest_opts: "--workers 4 --tests-per-worker 1 -k pins/tests"
36+
- os: "windows-latest"
37+
python: "3.10"
38+
# ignore doctests
3539
pytest_opts: "-k pins/tests"
3640
steps:
3741
- uses: actions/checkout@v2
3842
- uses: actions/setup-python@v2
3943
with:
4044
python-version: ${{ matrix.python }}
4145
- name: Install dependencies
46+
shell: bash
4247
run: |
4348
python -m pip install --upgrade pip
4449
@@ -57,14 +62,16 @@ jobs:
5762
export_default_credentials: true
5863

5964
- name: Run tests
65+
shell: bash
6066
run: |
61-
pytest pins -m 'not fs_rsc and not skip_on_github' --workers 4 --tests-per-worker 1 $PYTEST_OPTS
67+
pytest pins -m 'not fs_rsc and not skip_on_github' $PYTEST_OPTS
6268
env:
6369
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
6470
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
6571
AWS_REGION: "us-east-1"
6672
PYTEST_OPTS: ${{ matrix.pytest_opts }}
6773
REQUIREMENTS: ${{ matrix.requirements }}
74+
ACTION_OS: ${{ matrix.os }}
6875
# fixes error on macosx virtual machine with pytest-parallel
6976
# https://github.com/browsertron/pytest-parallel/issues/93
7077
no_proxy: "*"

pins/rsconnect/api.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,13 @@ def post_content_bundle(self, guid, fname, gzip=True) -> Bundle:
371371
if p.is_dir() and gzip:
372372
import tarfile
373373

374-
with tempfile.NamedTemporaryFile(mode="wb", suffix=".tar.gz") as tmp:
375-
with tarfile.open(fileobj=tmp.file, mode="w:gz") as tar:
376-
tar.add(str(p.absolute()), arcname="")
374+
with tempfile.TemporaryDirectory() as tmp_dir:
375+
p_archive = Path(tmp_dir) / "bundle.tar.gz"
377376

378-
# close the underlying file. note we don't call the top-level
379-
# close method, since that would delete the temporary file
380-
tmp.file.close()
377+
with tarfile.open(p_archive, mode="w:gz") as tar:
378+
tar.add(str(p.absolute()), arcname="")
381379

382-
with open(tmp.name, "rb") as f:
380+
with open(p_archive, "rb") as f:
383381
result = f_request(data=f)
384382
else:
385383
with open(str(p.absolute()), "rb") as f:

pins/tests/test_cache.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,23 @@
1010
)
1111

1212
from fsspec import filesystem
13+
from pathlib import Path
14+
15+
# NOTE: windows time.time() implementation appears to have 16 millisecond precision, so
16+
# we need to add a small delay, in order to avoid prune checks appearing to happen at the
17+
# exact same moment something earlier was created / accessed.
18+
# see: https://stackoverflow.com/a/1938096/1144523
1319

1420

1521
# Utilities ===================================================================
1622

1723

24+
def _sleep():
25+
# time-based issues keep arising erratically in windows checks, so try to shoot
26+
# well past
27+
time.sleep(0.3)
28+
29+
1830
@pytest.fixture
1931
def some_file(tmp_dir2):
2032
p = tmp_dir2 / "some_file.txt"
@@ -34,7 +46,7 @@ def test_touch_access_time_manual(some_file):
3446
def test_touch_access_time_auto(some_file):
3547
orig_access = some_file.stat().st_atime
3648

37-
time.sleep(0.2)
49+
_sleep()
3850
new_time = touch_access_time(some_file)
3951

4052
assert some_file.stat().st_atime == new_time
@@ -55,9 +67,14 @@ def test_pins_cache_url_hash_name():
5567
cache = PinsUrlCache(fs=filesystem("file"))
5668
hashed = cache.hash_name("http://example.com/a.txt", True)
5769

70+
p_hash = Path(hashed)
71+
5872
# should have form <url_hash>/<version_placeholder>/<filename>
59-
assert hashed.endswith("/a.txt")
60-
assert hashed.count("/") == 2
73+
assert p_hash.name == "a.txt"
74+
75+
# count parent dirs, excluding root (e.g. "." or "/")
76+
n_parents = len(p_hash.parents) - 1
77+
assert n_parents == 2
6178

6279

6380
@pytest.mark.skip("TODO")
@@ -106,6 +123,8 @@ def pin2_v3(a_cache):
106123

107124

108125
def test_cache_pruner_old_versions_none(a_cache, pin1_v1):
126+
_sleep()
127+
109128
pruner = CachePruner(a_cache)
110129

111130
old = pruner.old_versions(days=1)
@@ -114,6 +133,8 @@ def test_cache_pruner_old_versions_none(a_cache, pin1_v1):
114133

115134

116135
def test_cache_pruner_old_versions_days0(a_cache, pin1_v1):
136+
_sleep()
137+
117138
pruner = CachePruner(a_cache)
118139
old = pruner.old_versions(days=0)
119140

@@ -122,6 +143,8 @@ def test_cache_pruner_old_versions_days0(a_cache, pin1_v1):
122143

123144

124145
def test_cache_pruner_old_versions_some(a_cache, pin1_v1, pin1_v2):
146+
_sleep()
147+
125148
# create: tmp_dir/pin1/version1
126149

127150
pruner = CachePruner(a_cache)
@@ -133,6 +156,8 @@ def test_cache_pruner_old_versions_some(a_cache, pin1_v1, pin1_v2):
133156

134157

135158
def test_cache_pruner_old_versions_multi_pins(a_cache, pin1_v2, pin2_v3):
159+
_sleep()
160+
136161
pruner = CachePruner(a_cache)
137162
old = pruner.old_versions(days=1)
138163

@@ -141,6 +166,8 @@ def test_cache_pruner_old_versions_multi_pins(a_cache, pin1_v2, pin2_v3):
141166

142167

143168
def test_cache_prune_prompt(a_cache, pin1_v1, pin2_v3, monkeypatch):
169+
_sleep()
170+
144171
cache_prune(days=1, cache_root=a_cache.parent, prompt=False)
145172

146173
versions = list(a_cache.glob("*/*"))

pins/tests/test_constructors.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ def check_dir_writable(p_dir):
2525

2626

2727
def check_cache_file_path(p_file, p_cache):
28-
assert str(p_file.relative_to(p_cache)).count("/") == 2
28+
rel_path = p_file.relative_to(p_cache)
29+
30+
# parents has every entry you'd get if you called .parents all the way to some root.
31+
# for a relative path, the root is likely ".", so we subtract 1 to get the number
32+
# of parent directories.
33+
# note this essentially counts slashes, in a inter-OS friendly way.
34+
n_parents = len(rel_path.parents) - 1
35+
assert n_parents == 2
2936

3037

3138
def construct_from_board(board):

0 commit comments

Comments
 (0)