|
3 | 3 | from __future__ import annotations |
4 | 4 |
|
5 | 5 | import inspect |
6 | | -from typing import TYPE_CHECKING, Protocol |
| 6 | +import sys |
| 7 | +from typing import TYPE_CHECKING, Any, Protocol |
7 | 8 |
|
8 | 9 | import pytest |
9 | 10 | from inline_snapshot import external_file, register_format_alias |
|
14 | 15 | from collections.abc import Callable |
15 | 16 | from pathlib import Path |
16 | 17 |
|
| 18 | +if sys.version_info >= (3, 10): |
| 19 | + from datetime import datetime, timezone |
| 20 | + |
| 21 | + import time_machine |
| 22 | + |
| 23 | + def _parse_time_string(time_str: str) -> datetime: |
| 24 | + """Parse time string to datetime with UTC timezone.""" |
| 25 | + for fmt in ( |
| 26 | + "%Y-%m-%dT%H:%M:%S%z", |
| 27 | + "%Y-%m-%d %H:%M:%S%z", |
| 28 | + "%Y-%m-%dT%H:%M:%S", |
| 29 | + "%Y-%m-%d %H:%M:%S", |
| 30 | + "%Y-%m-%d", |
| 31 | + ): |
| 32 | + try: |
| 33 | + dt = datetime.strptime(time_str, fmt) # noqa: DTZ007 |
| 34 | + if dt.tzinfo is None: |
| 35 | + dt = dt.replace(tzinfo=timezone.utc) |
| 36 | + return dt # noqa: TRY300 |
| 37 | + except ValueError: # noqa: PERF203 |
| 38 | + continue |
| 39 | + return datetime.fromisoformat(time_str.replace("Z", "+00:00")) # pragma: no cover |
| 40 | + |
| 41 | + def freeze_time(time_to_freeze: str, **kwargs: Any) -> time_machine.travel: # noqa: ARG001 |
| 42 | + """Freeze time using time-machine (100-200x faster than freezegun).""" |
| 43 | + dt = _parse_time_string(time_to_freeze) |
| 44 | + return time_machine.travel(dt, tick=False) |
| 45 | + |
| 46 | +else: |
| 47 | + from freezegun import freeze_time as freeze_time # noqa: PLC0414 |
| 48 | + |
17 | 49 |
|
18 | 50 | def _normalize_line_endings(text: str) -> str: |
19 | 51 | """Normalize line endings to LF for cross-platform comparison.""" |
@@ -200,3 +232,13 @@ def _inline_snapshot_file_formats() -> None: |
200 | 232 | def min_version() -> str: |
201 | 233 | """Return minimum Python version as string.""" |
202 | 234 | return f"3.{MIN_VERSION}" |
| 235 | + |
| 236 | + |
| 237 | +@pytest.fixture(scope="session", autouse=True) |
| 238 | +def _preload_heavy_modules() -> None: |
| 239 | + """Pre-import heavy modules once per session to warm up the import cache. |
| 240 | +
|
| 241 | + This reduces per-test overhead when running with pytest-xdist, |
| 242 | + as each worker only pays the import cost once at session start. |
| 243 | + """ |
| 244 | + import datamodel_code_generator # noqa: PLC0415, F401 |
0 commit comments