Skip to content

Commit aa7cb1c

Browse files
authored
Fix compatibility with Windows (#3)
Windows normalizes case of environment variables (to uppercase), so stop relying on case-sensitivity there when passing data to workers.
1 parent 846ac1f commit aa7cb1c

File tree

2 files changed

+39
-41
lines changed

2 files changed

+39
-41
lines changed

src/geltest/_internal/fixtures.py

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from __future__ import annotations
2-
from typing import TYPE_CHECKING, Protocol
2+
from typing import TYPE_CHECKING, Any, Protocol
33
from typing_extensions import TypeAliasType, TypedDict, Required
44

55
import asyncio
@@ -45,7 +45,7 @@ async def setup_test_cases(
4545
options: Mapping[str, str] | None = None,
4646
num_jobs: int = 1,
4747
ui: loader.UI,
48-
) -> tuple[Stats, dict[str, object]]:
48+
) -> Stats:
4949
fixture_data: dict[str, object] = {}
5050
fixtures: list[loader.Fixture] = []
5151

@@ -72,7 +72,16 @@ async def setup_test_cases(
7272
for fixture in fixtures:
7373
await fixture.post_session_set_up(cases, ui=ui)
7474

75-
return stats, fixture_data
75+
class_data: dict[str, Mapping[str, object]] = {}
76+
for testcls in cases:
77+
if issubclass(testcls, loader.DatabaseTestCaseProto):
78+
key = f"{testcls.__module__}.{testcls.__qualname__}".upper()
79+
class_data[key] = testcls.get_shared_data()
80+
81+
export_global_fixture_data(fixture_data)
82+
export_class_fixture_data(class_data)
83+
84+
return stats
7685

7786

7887
async def tear_down_test_cases(
@@ -112,34 +121,38 @@ async def tear_down_test_cases(
112121

113122
@functools.cache
114123
def _find_all_global_fixture_data() -> dict[tuple[str, str, str], str]:
115-
result: dict[tuple[str, str, str], str] = {}
116-
117-
for env_var, serialized_data in os.environ.items():
118-
_, pfx, key = env_var.partition("GEL_TEST_GLOBAL_DATA_")
119-
if not pfx:
120-
# Not a global fixture data entry
121-
continue
122-
123-
clsfqname, sep, attr = key.partition(":")
124-
if not sep:
125-
# Improperly formatted key?
124+
result: dict[tuple[str, str, str], Any] = {}
125+
data = os.environ.get("GEL_TEST_GLOBAL_DATA")
126+
if data:
127+
try:
128+
values = json.loads(data)
129+
if not isinstance(values, dict):
130+
raise ValueError("expected a dict in GEL_TEST_GLOBAL_DATA")
131+
except ValueError:
126132
# XXX: log a warning
127-
continue
133+
values = {}
128134

129-
modname, dot, clsname = clsfqname.rpartition(".")
130-
if not dot:
131-
# Improperly formatted key?
132-
# XXX: log a warning
133-
continue
135+
for key, value in values.items():
136+
clsfqname, sep, attr = key.partition(":")
137+
if not sep:
138+
# Improperly formatted key?
139+
# XXX: log a warning
140+
continue
134141

135-
result[modname, clsname, attr] = serialized_data
142+
modname, dot, clsname = clsfqname.rpartition(".")
143+
if not dot:
144+
# Improperly formatted key?
145+
# XXX: log a warning
146+
continue
147+
148+
result[modname, clsname, attr] = value
136149

137150
return result
138151

139152

140153
def import_global_fixture_data() -> None:
141154
fixture_data = _find_all_global_fixture_data()
142-
for (modname, clsname, attr), serialized_data in fixture_data.items():
155+
for (modname, clsname, attr), data in fixture_data.items():
143156
if (
144157
# the module containing the class was imported
145158
(mod := sys.modules.get(modname)) is not None
@@ -151,20 +164,14 @@ def import_global_fixture_data() -> None:
151164
loader.Fixture,
152165
)
153166
):
154-
try:
155-
data = json.loads(serialized_data)
156-
except ValueError:
157-
# XXX: log a warning
158-
pass
159-
else:
160-
fixture.set_shared_data(data)
167+
fixture.set_shared_data(data)
161168

162169

163170
def import_class_fixture_data(cls: type[unittest.TestCase]) -> None:
164171
if not issubclass(cls, loader.DatabaseTestCaseProto):
165172
return
166173
cls_key = f"{cls.__module__}.{cls.__qualname__}"
167-
env_key = f"GEL_TEST_CLASS_DATA_{cls_key}"
174+
env_key = f"GEL_TEST_CLASS_DATA_{cls_key.upper()}"
168175
data_string = os.environ.get(env_key, "")
169176
if data_string:
170177
class_data = json.loads(data_string)
@@ -176,8 +183,7 @@ def import_class_fixture_data(cls: type[unittest.TestCase]) -> None:
176183
def export_global_fixture_data(
177184
global_fixture_data: Mapping[str, object],
178185
) -> None:
179-
for key, data in global_fixture_data.items():
180-
os.environ[f"GEL_TEST_GLOBAL_DATA_{key}"] = json.dumps(data)
186+
os.environ["GEL_TEST_GLOBAL_DATA"] = json.dumps(global_fixture_data)
181187

182188

183189
def export_class_fixture_data(

src/geltest/_internal/runner.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ def run(
12511251
teardown_stats = []
12521252

12531253
try:
1254-
setup_stats, fixture_data = asyncio.run(
1254+
setup_stats = asyncio.run(
12551255
fixtures.setup_test_cases(
12561256
[*cases],
12571257
num_jobs=self.num_workers,
@@ -1261,15 +1261,7 @@ def run(
12611261
)
12621262
bootstrap_time_taken = time.monotonic() - session_start
12631263

1264-
class_data: dict[str, Mapping[str, object]] = {}
1265-
for testcls in cases:
1266-
if issubclass(testcls, loader.DatabaseTestCaseProto):
1267-
key = f"{testcls.__module__}.{testcls.__qualname__}"
1268-
class_data[key] = testcls.get_shared_data()
1269-
12701264
os.environ["GEL_TEST_SETUP_RESPONSIBLE"] = "runner"
1271-
fixtures.export_global_fixture_data(fixture_data)
1272-
fixtures.export_class_fixture_data(class_data)
12731265

12741266
start = time.monotonic()
12751267

0 commit comments

Comments
 (0)