Skip to content

Commit 71733d8

Browse files
committed
fix(dlt): compare dlt version semantically for destination client
The dlt destination-client gate compared the version as a string (`dlt.__version__ >= "1.10.0"`). String comparison is lexicographic, so it wrongly evaluates "1.9.0" >= "1.10.0" (and "1.2.0", "1.5.10", ...) as True. That sent every 1.x version down the >=1.10.0 branch and made the pre-1.10 `_sql_job_client` fallback unreachable. Use `packaging.version.parse` for a semantic comparison, mirroring the existing idiom in sqlmesh/core/config/connection.py. The client selection is extracted into a small `_get_destination_client` helper so the version gate can be unit tested without a live dlt pipeline. Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
1 parent b43743a commit 71733d8

2 files changed

Lines changed: 67 additions & 5 deletions

File tree

sqlmesh/integrations/dlt.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
import typing as t
22
import click
33
from datetime import datetime, timedelta, timezone
4+
from packaging import version
45
from pydantic import ValidationError
56
from sqlglot import exp, parse_one
67
from sqlmesh.core.config.connection import parse_connection_config
78
from sqlmesh.core.context import Context
89
from sqlmesh.utils.date import yesterday_ds
910

1011

12+
def _get_destination_client(pipeline: t.Any, schema: t.Any) -> t.Any:
13+
"""Return the dlt destination client, handling the 1.10.0 API change.
14+
15+
dlt 1.10.0 replaced the private ``_sql_job_client`` with the public
16+
``destination_client``. The version must be compared semantically rather
17+
than lexicographically: a string comparison wrongly evaluates
18+
``"1.9.0" >= "1.10.0"`` as ``True``.
19+
"""
20+
import dlt
21+
22+
if version.parse(dlt.__version__) >= version.parse("1.10.0"):
23+
return pipeline.destination_client()
24+
return pipeline._sql_job_client(schema) # type: ignore
25+
26+
1127
def generate_dlt_models_and_settings(
1228
pipeline_name: str,
1329
dialect: str,
@@ -63,10 +79,7 @@ def generate_dlt_models_and_settings(
6379
if db_type == "filesystem":
6480
connection_config = None
6581
else:
66-
if dlt.__version__ >= "1.10.0":
67-
client = pipeline.destination_client()
68-
else:
69-
client = pipeline._sql_job_client(schema) # type: ignore
82+
client = _get_destination_client(pipeline, schema)
7083
config = client.config
7184
credentials = config.credentials
7285
configs = {

tests/integrations/test_dlt.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,53 @@
1-
from sqlmesh.integrations.dlt import generate_incremental_model
1+
import typing as t
2+
3+
import pytest
4+
5+
from sqlmesh.integrations.dlt import _get_destination_client, generate_incremental_model
6+
7+
8+
class _FakePipeline:
9+
"""Records which destination-client accessor the version gate selects."""
10+
11+
def __init__(self) -> None:
12+
self.called: t.Optional[str] = None
13+
14+
def destination_client(self) -> str:
15+
self.called = "destination_client"
16+
return self.called
17+
18+
def _sql_job_client(self, schema: t.Any) -> str:
19+
self.called = "_sql_job_client"
20+
return self.called
21+
22+
23+
@pytest.mark.parametrize(
24+
"dlt_version, expected",
25+
[
26+
("1.9.0", "_sql_job_client"),
27+
("1.2.0", "_sql_job_client"),
28+
("1.5.10", "_sql_job_client"),
29+
("1.10.0", "destination_client"),
30+
("1.28.1", "destination_client"),
31+
("2.0.0", "destination_client"),
32+
],
33+
)
34+
def test_get_destination_client_version_gate(
35+
monkeypatch: pytest.MonkeyPatch, dlt_version: str, expected: str
36+
) -> None:
37+
# The dlt destination-client API changed in 1.10.0: the public
38+
# destination_client() replaced the private _sql_job_client(). The version
39+
# gate must compare semantically (packaging.version.parse), not
40+
# lexicographically. A string compare wrongly treats "1.9.0" >= "1.10.0" as
41+
# True, which would send every 1.x version down the >=1.10.0 branch and make
42+
# the pre-1.10 fallback unreachable.
43+
import dlt
44+
45+
monkeypatch.setattr(dlt, "__version__", dlt_version)
46+
pipeline = _FakePipeline()
47+
48+
_get_destination_client(pipeline, schema=None)
49+
50+
assert pipeline.called == expected
251

352

453
def test_generate_incremental_model_filters_on_timestamp_macros() -> None:

0 commit comments

Comments
 (0)