Skip to content

Commit 4d86777

Browse files
committed
Add build-native CI step
1 parent 3fc3594 commit 4d86777

File tree

5 files changed

+74
-36
lines changed

5 files changed

+74
-36
lines changed

.github/workflows/dissect-ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ on:
1010

1111
jobs:
1212
ci:
13-
uses: fox-it/dissect-workflow-templates/.github/workflows/dissect-ci-template.yml@main
13+
uses: fox-it/dissect-workflow-templates/.github/workflows/dissect-ci-template.yml@build-native
1414
secrets: inherit
1515
with:
16+
build-native: true
1617
run-benchmarks: true
1718

1819
publish:
@@ -25,7 +26,7 @@ jobs:
2526
steps:
2627
- uses: actions/download-artifact@v4
2728
with:
28-
name: packages
29+
pattern: packages-*
2930
path: dist/
3031
# According to the documentation, it automatically looks inside the `dist/` folder for packages.
3132
- name: Publish package distributions to Pypi

dissect/util/ts.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
from __future__ import annotations
22

33
import struct
4-
import sys
54
from datetime import datetime, timedelta, timezone
65

7-
if sys.platform in ("win32", "emscripten"):
6+
try:
7+
datetime.fromtimestamp(-6969696969, tz=timezone.utc)
8+
9+
def _calculate_timestamp(ts: float) -> datetime:
10+
"""Calculate timestamps normally."""
11+
return datetime.fromtimestamp(ts, tz=timezone.utc)
12+
except (OSError, OverflowError):
813
_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
914

1015
def _calculate_timestamp(ts: float) -> datetime:
@@ -16,12 +21,6 @@ def _calculate_timestamp(ts: float) -> datetime:
1621
"""
1722
return _EPOCH + timedelta(seconds=ts)
1823

19-
else:
20-
21-
def _calculate_timestamp(ts: float) -> datetime:
22-
"""Calculate timestamps normally."""
23-
return datetime.fromtimestamp(ts, tz=timezone.utc)
24-
2524

2625
def now() -> datetime:
2726
"""Return an aware datetime object of the current time in UTC."""

tests/conftest.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,40 @@
33
import pytest
44

55

6+
def pytest_addoption(parser: pytest.Parser) -> None:
7+
parser.addoption(
8+
"--force-native", action="store_true", default=False, help="run native tests, not allowing fallbacks"
9+
)
10+
11+
612
@pytest.fixture(scope="session", params=[True, False], ids=["native", "python"])
7-
def lz4(request: pytest.FixtureRequest) -> ModuleType:
13+
def _native(request: pytest.FixtureRequest, pytestconfig: pytest.Config) -> ModuleType:
814
if request.param:
9-
return pytest.importorskip("dissect.util._native", reason="_native module is unavailable").compression.lz4
15+
try:
16+
import dissect.util._native
17+
except ImportError:
18+
(pytest.fail if pytestconfig.getoption("--force-native") else pytest.skip)("_native module is unavailable")
19+
else:
20+
return dissect.util._native
1021

11-
return pytest.importorskip("dissect.util.compression.lz4")
22+
return None
1223

1324

14-
@pytest.fixture(scope="session", params=[True, False], ids=["native", "python"])
15-
def lzo(request: pytest.FixtureRequest) -> ModuleType:
16-
if request.param:
17-
return pytest.importorskip("dissect.util._native", reason="_native module is unavailable").compression.lzo
25+
@pytest.fixture(scope="session")
26+
def lz4(_native: ModuleType) -> ModuleType:
27+
if _native:
28+
return _native.compression.lz4
29+
30+
import dissect.util.compression.lz4
31+
32+
return dissect.util.compression.lz4
33+
34+
35+
@pytest.fixture(scope="session")
36+
def lzo(_native: ModuleType) -> ModuleType:
37+
if _native:
38+
return _native.compression.lzo
39+
40+
import dissect.util.compression.lzo
1841

19-
return pytest.importorskip("dissect.util.compression.lzo")
42+
return dissect.util.compression.lzo

tests/test_ts.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1-
import platform
21
from datetime import datetime, timedelta, timezone
32
from importlib import reload
43
from types import ModuleType
4+
from typing import NoReturn
55
from unittest.mock import patch
66

77
import pytest
88

99

10-
@pytest.fixture(params=["windows", "emscripten", "linux"])
10+
@pytest.fixture(params=[True, False])
1111
def imported_ts(request: pytest.FixtureRequest) -> ModuleType:
12-
with patch.object(platform, "system", return_value=request.param):
13-
from dissect.util import ts
12+
from dissect.util import ts
13+
14+
if request.param:
15+
16+
class MockDatetime(datetime):
17+
@classmethod
18+
def fromtimestamp(cls, *args, **kwargs) -> NoReturn:
19+
raise OverflowError("Mock overflow error")
1420

15-
return reload(ts)
21+
with patch("datetime.datetime", MockDatetime):
22+
return reload(ts)
23+
24+
return reload(ts)
1625

1726

1827
@pytest.fixture
@@ -32,32 +41,32 @@ def test_now(ts: ModuleType) -> None:
3241
assert ts_now.tzinfo == timezone.utc
3342

3443

35-
def test_unix_now(imported_ts: ModuleType) -> None:
36-
timestamp = imported_ts.unix_now()
44+
def test_unix_now(ts: ModuleType) -> None:
45+
timestamp = ts.unix_now()
3746

3847
assert isinstance(timestamp, int)
3948
assert datetime.fromtimestamp(timestamp, tz=timezone.utc).microsecond == 0
4049

4150

42-
def test_unix_now_ms(imported_ts: ModuleType) -> None:
43-
timestamp = imported_ts.unix_now_ms()
51+
def test_unix_now_ms(ts: ModuleType) -> None:
52+
timestamp = ts.unix_now_ms()
4453

4554
assert isinstance(timestamp, int)
46-
assert imported_ts.from_unix_ms(timestamp).microsecond == (timestamp % 1e3) * 1000
55+
assert ts.from_unix_ms(timestamp).microsecond == (timestamp % 1e3) * 1000
4756

4857

49-
def test_unix_now_us(imported_ts: ModuleType) -> None:
50-
timestamp = imported_ts.unix_now_us()
58+
def test_unix_now_us(ts: ModuleType) -> None:
59+
timestamp = ts.unix_now_us()
5160

5261
assert isinstance(timestamp, int)
53-
assert imported_ts.from_unix_us(timestamp).microsecond == timestamp % 1e6
62+
assert ts.from_unix_us(timestamp).microsecond == timestamp % 1e6
5463

5564

56-
def test_unix_now_ns(imported_ts: ModuleType) -> None:
57-
timestamp = imported_ts.unix_now_ns()
65+
def test_unix_now_ns(ts: ModuleType) -> None:
66+
timestamp = ts.unix_now_ns()
5867

5968
assert isinstance(timestamp, int)
60-
assert imported_ts.from_unix_ns(timestamp).microsecond == int((timestamp // 1000) % 1e6)
69+
assert ts.from_unix_ns(timestamp).microsecond == int((timestamp // 1000) % 1e6)
6170

6271

6372
def test_to_unix(ts: ModuleType) -> None:

tox.ini

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ deps =
1717
config_settings_build_wheel = --build-option=--py-limited-api=cp39
1818

1919
[testenv]
20-
package = wheel
2120
deps =
2221
pytest
2322
pytest-cov
@@ -27,6 +26,13 @@ commands =
2726
coverage report
2827
coverage xml
2928

29+
[testenv:native]
30+
package = wheel
31+
deps =
32+
pytest
33+
commands =
34+
pytest --basetemp="{envtmpdir}" --import-mode="append" --force-native {posargs:--color=yes -v tests}
35+
3036
[testenv:benchmark]
3137
deps =
3238
pytest
@@ -35,7 +41,7 @@ deps =
3541
passenv =
3642
CODSPEED_ENV
3743
commands =
38-
pytest --basetemp="{envtmpdir}" {posargs:--color=yes -v tests}
44+
pytest --basetemp="{envtmpdir}" --import-mode="append" {posargs:--color=yes -v tests}
3945

4046
[testenv:build]
4147
package = skip

0 commit comments

Comments
 (0)