Skip to content

Commit fa02892

Browse files
authored
Merge pull request #3267 from dlt-hub/devel
master merge for 1.18.1 release
2 parents 0da0091 + 192296f commit fa02892

File tree

24 files changed

+266
-98
lines changed

24 files changed

+266
-98
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ jobs:
6666
needs: test_common
6767
uses: ./.github/workflows/test_sources_local.yml
6868

69-
# test_hub:
70-
# name: test dlthub features
71-
# needs: lint
72-
# uses: ./.github/workflows/test_hub.yml
69+
test_hub:
70+
name: test dlthub features
71+
needs: lint
72+
uses: ./.github/workflows/test_hub.yml
7373

7474
test_tools_airflow:
7575
name: test airflow helpers

.github/workflows/test_docs_snippets.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@ on:
77

88
env:
99

10-
# RUNTIME__SENTRY_DSN: https://[email protected]/4504819859914752
1110
RUNTIME__LOG_LEVEL: ERROR
1211

13-
# Path to local qdrant database
14-
DESTINATION__QDRANT__CREDENTIALS__PATH: zendesk.qdb
1512
# detect if the workflow is executed in a repo fork
1613
IS_FORK: ${{ github.event.pull_request.head.repo.fork }}
1714

@@ -48,8 +45,8 @@ jobs:
4845
with:
4946
ref: ${{ github.event.pull_request.head.sha || github.ref }}
5047

51-
- name: Start weaviate
52-
run: docker compose -f "tests/load/weaviate/docker-compose.yml" up -d
48+
# - name: Start weaviate
49+
# run: docker compose -f "tests/load/weaviate/docker-compose.yml" up -d
5350

5451
- name: Setup node 20
5552
uses: actions/setup-node@v4
@@ -69,10 +66,10 @@ jobs:
6966
enable-cache: true
7067

7168
- name: Install dependencies
72-
run: uv sync --extra duckdb --extra weaviate --extra parquet --extra qdrant --extra bigquery --extra postgres --extra lancedb --extra s3 --extra workspace --group docs --group sentry-sdk --group ibis --group providers
69+
run: uv sync --extra duckdb --extra parquet --extra postgres --extra s3 --extra workspace --group docs --group sentry-sdk --group ibis --group providers
7370

74-
# - name: Install dlthub incl alpha releases
75-
# run: uv run pip install --pre dlthub
71+
- name: Install dlthub incl alpha releases
72+
run: uv run pip install --pre dlthub
7673

7774
- name: run docs preprocessor
7875
run: make preprocess-docs

.github/workflows/test_hub.yml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,22 @@ jobs:
1818
fail-fast: false
1919
matrix:
2020
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
21-
python-version: ["3.10", "3.11", "3.12"]
21+
python-version: ["3.10", "3.11", "3.12", "3.13"]
2222
dlthub_dep: ["dlthub", "https://dlt-packages.fra1.digitaloceanspaces.com/dlthub/dlthub-0.0.0+nightly-py3-none-any.whl"]
2323
# Test all python versions on ubuntu only
2424
exclude:
2525
- os: "macos-latest"
26-
python-version: "3.11"
26+
python-version: "3.10"
2727
- os: "macos-latest"
2828
python-version: "3.12"
29+
- os: "macos-latest"
30+
python-version: "3.13"
2931
- os: "windows-latest"
30-
python-version: "3.11"
32+
python-version: "3.10"
3133
- os: "windows-latest"
3234
python-version: "3.12"
35+
- os: "windows-latest"
36+
python-version: "3.13"
3337

3438
defaults:
3539
run:
@@ -58,19 +62,30 @@ jobs:
5862
sudo ACCEPT_EULA=Y apt-get install --yes msodbcsql18
5963
if: matrix.os == 'ubuntu-latest'
6064

65+
# still does not work in mac
66+
# - name: Install ODBC driver for SQL Server (macOS)
67+
# if: matrix.os == 'macos-latest'
68+
# env:
69+
# HOMEBREW_NONINTERACTIVE: 1
70+
# HOMEBREW_NO_AUTO_UPDATE: 1
71+
# HOMEBREW_NO_ANALYTICS: 1
72+
# HOMEBREW_NO_INSTALL_CLEANUP: 1
73+
# run: |
74+
# brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release
75+
# printf "YES\n" | brew install msodbcsql18
76+
# # quick diagnostics (do not fail the build if unavailable)
77+
# odbcinst -j || true
78+
# odbcinst -q -d || true
79+
6180
- name: Install all dependencies
6281
run: make dev
6382

64-
- name: Install dlthub nightly devel build without cache
83+
- name: Install dlthub
6584
run: uv run pip install --upgrade --force-reinstall --no-cache-dir ${{ matrix.dlthub_dep }}
6685

6786
- name: Run tests
6887
run: pytest tests/hub
69-
if: matrix.os == 'ubuntu-latest'
70-
71-
- name: Run tests on mac on win without mssql driver
72-
run: pytest tests/hub -m "not mssql"
73-
if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest'
88+
# if: matrix.os != 'macos-latest'
7489

7590
matrix_job_required_check:
7691
name: hub | dlthub features tests

Makefile

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ lint-snippets:
7575
uv run flake8 --max-line-length=200 docs/website docs/tools --exclude docs/website/.dlt-repo,docs/website/node_modules
7676

7777
lint-and-test-snippets: lint-snippets
78-
cd docs/website/docs && uv run pytest --ignore=node_modules --ignore hub/features/transformations/transformation-snippets.py
78+
cd docs/website/docs && uv run pytest --ignore=node_modules
7979

8080
lint-and-test-examples:
8181
uv pip install docstring_parser_fork --reinstall
@@ -134,18 +134,17 @@ clean-dist:
134134

135135
publish-library: clean-dist build-library
136136
ls -l dist/
137-
@read -sp "Enter PyPI API token: " PYPI_API_TOKEN; echo ; \
138-
uv publish --token "$$PYPI_API_TOKEN"
137+
@bash -c 'read -s -p "Enter PyPI API token: " PYPI_API_TOKEN; echo; \
138+
uv publish --token "$$PYPI_API_TOKEN"'
139139

140140
test-build-images: build-library
141141
# NOTE: uv export does not work with our many different deps, we install a subset and freeze
142-
uv sync --extra gcp --extra redshift --extra duckdb
143-
uv pip freeze > _gen_requirements.txt
142+
# uv sync --extra gcp --extra redshift --extra duckdb
143+
# uv pip freeze > _gen_requirements.txt
144144
# filter out libs that need native compilation
145-
grep `cat compiled_packages.txt` _gen_requirements.txt > compiled_requirements.txt
145+
# grep `cat compiled_packages.txt` _gen_requirements.txt > compiled_requirements.txt
146146
docker build -f deploy/dlt/Dockerfile.airflow --build-arg=COMMIT_SHA="$(shell git log -1 --pretty=%h)" --build-arg=IMAGE_VERSION="$(shell uv version --short)" .
147-
# enable when we upgrade arrow to 20.x
148-
# docker build -f deploy/dlt/Dockerfile --build-arg=COMMIT_SHA="$(shell git log -1 --pretty=%h)" --build-arg=IMAGE_VERSION="$(shell uv version)" .
147+
docker build -f deploy/dlt/Dockerfile.minimal --build-arg=COMMIT_SHA="$(shell git log -1 --pretty=%h)" --build-arg=IMAGE_VERSION="$(shell uv version --short)" .
149148

150149
preprocess-docs:
151150
# run docs preprocessing to run a few checks and ensure examples can be parsed

deploy/dlt/Dockerfile.minimal

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
FROM python:3.11.11-alpine
2+
3+
# Metadata
4+
LABEL org.label-schema.vendor="dltHub" \
5+
org.label-schema.url="https://dlthub.com" \
6+
org.label-schema.name="dlt" \
7+
org.label-schema.description="**data load tool (dlt)** is a simple, open source Python library that makes data loading easy."
8+
9+
# prepare dirs to install dlt
10+
RUN mkdir -p /tmp/pydlt
11+
12+
WORKDIR /tmp/pydlt
13+
14+
# install alpine deps
15+
RUN apk update &&\
16+
apk add --no-cache ca-certificates curl &&\
17+
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && python3 get-pip.py &&\
18+
rm get-pip.py &&\
19+
pip install --upgrade setuptools wheel pip
20+
21+
22+
# add build labels and envs
23+
ARG COMMIT_SHA=""
24+
ARG IMAGE_VERSION=""
25+
LABEL commit_sha=${COMMIT_SHA}
26+
LABEL version=${IMAGE_VERSION}
27+
ENV COMMIT_SHA=${COMMIT_SHA}
28+
ENV IMAGE_VERSION=${IMAGE_VERSION}
29+
30+
# install exactly the same version of the library we used to build
31+
COPY dist/dlt-${IMAGE_VERSION}.tar.gz .
32+
RUN pip install /tmp/pydlt/dlt-${IMAGE_VERSION}.tar.gz
33+
34+
# create app dir to run simple test
35+
RUN mkdir -p /app
36+
WORKDIR /app
37+
RUN rm -r /tmp/pydlt
38+
39+
# make sure dlt can be actually imported
40+
RUN python -c 'import dlt;import pendulum;'
41+
42+
# check excluded imports
43+
COPY deploy/dlt/restrict_imports.py .
44+
RUN python restrict_imports.py
45+
46+
# run simple pipeline
47+
COPY deploy/dlt/minimal_pipeline.py .
48+
RUN python minimal_pipeline.py
49+
RUN dlt pipeline fruit_pipeline info
50+
51+
# enable workspace
52+
RUN mkdir -p .dlt && touch .dlt/.workspace
53+
# RUN dlt pipeline fruit_pipeline info
54+
RUN dlt workspace info
55+
RUN python minimal_pipeline.py
56+
RUN dlt pipeline fruit_pipeline info

deploy/dlt/minimal_pipeline.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import dlt
2+
from dlt._workspace._templates._single_file_templates.fruitshop_pipeline import (
3+
fruitshop as fruitshop_source,
4+
)
5+
6+
pf = dlt.pipeline(pipeline_name="fruit_pipeline", destination=dlt.destinations.filesystem("_data"))
7+
print(pf.run(fruitshop_source()))

deploy/dlt/restrict_imports.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
print("this module checks if certain modules are not imported by default")
2+
import sys, dlt
3+
4+
5+
# plugin system should not be initialized on dlt import, workspace should not be imported
6+
excluded_imports = ["dlt._workspace._workspace_context", "pluggy", "git"]
7+
8+
for excluded in excluded_imports:
9+
assert excluded not in sys.modules
10+
11+
12+
# will instantiate pluggy
13+
dlt.current.run_context()
14+
15+
assert "pluggy" in sys.modules
16+
assert "dlt._workspace._workspace_context" not in sys.modules

dlt/_workspace/_plugins.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import os
22
from typing import Any, Dict, Optional
33

4-
from dlt._workspace.exceptions import WorkspaceRunContextNotAvailable
5-
from dlt._workspace.profile import DEFAULT_PROFILE, read_profile_pin
64
from dlt.common.configuration import plugins as _plugins
75
from dlt.common.configuration.specs.pluggable_run_context import RunContextBase
8-
from dlt.common.runtime.run_context import RunContext
9-
10-
from dlt._workspace.run_context import default_name
11-
from dlt._workspace._workspace_context import (
12-
WorkspaceRunContext,
13-
is_workspace_dir,
14-
)
6+
from dlt.common.runtime.run_context import DOT_DLT, RunContext
157

168
__all__ = ["plug_workspace_context_impl"]
179

1810

11+
def is_workspace_dir(run_dir: str) -> bool:
12+
"""Checks if `run_dir` contains dlt workspace, this is true if a config file is found"""
13+
return os.path.isfile(os.path.join(run_dir, DOT_DLT, ".workspace"))
14+
15+
1916
@_plugins.hookimpl(specname="plug_run_context", trylast=False)
2017
def plug_workspace_context_impl(
2118
run_dir: Optional[str], runtime_kwargs: Optional[Dict[str, Any]]
@@ -24,12 +21,19 @@ def plug_workspace_context_impl(
2421
# if runtime_kwargs.get("_look_recursive")
2522
run_dir = os.path.abspath(run_dir or ".")
2623
if is_workspace_dir(run_dir):
24+
# import workspace only when context detected
25+
from dlt._workspace.profile import DEFAULT_PROFILE, read_profile_pin
26+
from dlt._workspace.run_context import default_name
27+
from dlt._workspace._workspace_context import WorkspaceRunContext
28+
2729
profile: str = None
2830
if runtime_kwargs:
2931
profile = runtime_kwargs.get("profile")
3032
profile = profile or read_profile_pin(RunContext(run_dir)) or DEFAULT_PROFILE
3133
return WorkspaceRunContext(default_name(run_dir), run_dir, profile)
3234
elif runtime_kwargs and runtime_kwargs.get("_required") == "WorkspaceRunContext":
35+
from dlt._workspace.exceptions import WorkspaceRunContextNotAvailable
36+
3337
raise WorkspaceRunContextNotAvailable(run_dir)
3438

3539
return None

dlt/_workspace/_workspace_context.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,22 +187,6 @@ def switch_profile(self, new_profile: str) -> "WorkspaceRunContext":
187187
switch_profile = copy_sig_ret(_switch_profile, WorkspaceRunContext)(_switch_profile)
188188

189189

190-
def is_workspace_dir(run_dir: str) -> bool:
191-
"""Checks if `project_dir` contains dlt project, this is true if a config file is found"""
192-
if os.path.isfile(os.path.join(run_dir, DOT_DLT, ".workspace")):
193-
return True
194-
return False
195-
196-
197-
def is_workspace_active() -> bool:
198-
try:
199-
active()
200-
except WorkspaceRunContextNotAvailable:
201-
return False
202-
else:
203-
return True
204-
205-
206190
def active() -> WorkspaceRunContext:
207191
"""Returns currently active Workspace"""
208192
ctx = Container()[PluggableRunContext].context

dlt/_workspace/cli/_plugins.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
from typing import Type
1111

1212
from dlt.common.configuration import plugins
13+
from dlt.common.runtime.run_context import active as run_context_active
1314

14-
from dlt._workspace._workspace_context import is_workspace_active
1515

1616
__all__ = [
1717
"plug_cli_init",
@@ -27,6 +27,13 @@
2727
]
2828

2929

30+
def is_workspace_active() -> bool:
31+
# verify run context type without importing
32+
33+
ctx = run_context_active()
34+
return ctx.__class__.__name__ == "WorkspaceRunContext"
35+
36+
3037
@plugins.hookimpl(specname="plug_cli")
3138
def plug_cli_init() -> Type[plugins.SupportsCliCommand]:
3239
from dlt._workspace.cli.commands import InitCommand

0 commit comments

Comments
 (0)