mirror of
https://github.com/dlt-hub/dlt.git
synced 2025-12-17 19:31:30 +00:00
docs: add runtime docs to CLI reference (#3445)
* bumps to version 1.20.0 * update the hub reference docs, add CI check * use dependency specifier in hub for plugin version check * minimum dlt runtime cli check * rollaback to old fsspec min version * fixes test_hub ci workflow * fixes flaky test * bumps hub extra * updates cli docs linting * fixes docs lock --------- Co-authored-by: Marcin Rudolf <rudolfix@rudolfix.org> Co-authored-by: ivasio <ivan@dlthub.com>
This commit is contained in:
11
.github/workflows/test_hub.yml
vendored
11
.github/workflows/test_hub.yml
vendored
@@ -94,6 +94,17 @@ jobs:
|
|||||||
run: pytest tests/hub
|
run: pytest tests/hub
|
||||||
# if: matrix.os != 'macos-latest'
|
# if: matrix.os != 'macos-latest'
|
||||||
|
|
||||||
|
- name: Test runtime client
|
||||||
|
run: |
|
||||||
|
mkdir .dlt && touch .dlt/.workspace
|
||||||
|
dlt runtime --help
|
||||||
|
|
||||||
|
# DISABLED: because docs rendering happens in non-deterministic order (of plugin discovery)
|
||||||
|
# must be fixed
|
||||||
|
# - name: Check that dlthub cli docs are up to date
|
||||||
|
# run: cd docs/tools/dlthub_cli && make check-cli-docs
|
||||||
|
# if: ${{ matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest' }}
|
||||||
|
|
||||||
matrix_job_required_check:
|
matrix_job_required_check:
|
||||||
name: hub | dlthub features tests
|
name: hub | dlthub features tests
|
||||||
needs: run_hub_features
|
needs: run_hub_features
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ COPY dist/dlt-${IMAGE_VERSION}.tar.gz .
|
|||||||
RUN mkdir -p /app
|
RUN mkdir -p /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN uv venv && uv pip install /tmp/pydlt/dlt-${IMAGE_VERSION}.tar.gz --resolution lowest-direct && uv pip install typing-extensions==4.8.0
|
RUN uv venv && uv pip install /tmp/pydlt/dlt-${IMAGE_VERSION}.tar.gz --resolution lowest-direct && uv pip install typing-extensions==4.8.0
|
||||||
RUN rm -r /tmp/pydlt
|
# RUN rm -r /tmp/pydlt
|
||||||
|
|
||||||
# make sure dlt can be actually imported
|
# make sure dlt can be actually imported
|
||||||
RUN uv run python -c 'import dlt;import pendulum;'
|
RUN uv run python -c 'import dlt;import pendulum;'
|
||||||
@@ -50,7 +50,12 @@ RUN uv run dlt pipeline fruit_pipeline info
|
|||||||
|
|
||||||
# enable workspace
|
# enable workspace
|
||||||
RUN mkdir -p .dlt && touch .dlt/.workspace
|
RUN mkdir -p .dlt && touch .dlt/.workspace
|
||||||
# RUN dlt pipeline fruit_pipeline info
|
RUN uv run dlt workspace -v info
|
||||||
RUN uv run dlt workspace info
|
|
||||||
RUN uv run python minimal_pipeline.py
|
RUN uv run python minimal_pipeline.py
|
||||||
RUN uv run dlt pipeline fruit_pipeline info
|
RUN uv run dlt pipeline fruit_pipeline info
|
||||||
|
|
||||||
|
# install hub
|
||||||
|
RUN uv pip install /tmp/pydlt/dlt-${IMAGE_VERSION}.tar.gz[hub] --resolution lowest-direct && uv pip install typing-extensions==4.8.0
|
||||||
|
RUN uv run python minimal_pipeline.py
|
||||||
|
RUN uv run dlt --non-interactive license issue dlthub.transformation
|
||||||
|
RUN uv run dlt runtime --help
|
||||||
@@ -6,7 +6,7 @@ from types import ModuleType
|
|||||||
from typing import Any, Dict, Iterator, List, Optional
|
from typing import Any, Dict, Iterator, List, Optional
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from packaging.version import Version
|
from packaging.specifiers import SpecifierSet
|
||||||
|
|
||||||
from dlt.common import known_env
|
from dlt.common import known_env
|
||||||
from dlt.common.configuration.container import Container
|
from dlt.common.configuration.container import Container
|
||||||
@@ -246,9 +246,14 @@ def ensure_plugin_version_match(
|
|||||||
plugin_version: str,
|
plugin_version: str,
|
||||||
plugin_module_name: str,
|
plugin_module_name: str,
|
||||||
dlt_extra: str,
|
dlt_extra: str,
|
||||||
|
dlt_version_specifier: Optional[SpecifierSet] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensures that installed dlt version matches plugin version. Plugins are tightly bound to `dlt`
|
"""Ensures that installed plugin version matches dlt requirements. Plugins are tightly bound
|
||||||
and released together. Both major and minor version must match. For alpha plugins version may be 0.
|
to `dlt` and released together.
|
||||||
|
|
||||||
|
If `dlt_version_specifier` is provided, it is used to check if the plugin version satisfies
|
||||||
|
the specifier. Otherwise, the specifier is read from dlt's package metadata (Requires-Dist).
|
||||||
|
If specifier cannot be determined, the function returns without checking.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
pkg_name: Name of the plugin package (e.g., "dlthub")
|
pkg_name: Name of the plugin package (e.g., "dlthub")
|
||||||
@@ -256,30 +261,37 @@ def ensure_plugin_version_match(
|
|||||||
plugin_version: The installed plugin version string
|
plugin_version: The installed plugin version string
|
||||||
plugin_module_name: The module name for MissingDependencyException (e.g., "dlthub")
|
plugin_module_name: The module name for MissingDependencyException (e.g., "dlthub")
|
||||||
dlt_extra: The dlt extra to install the plugin (e.g., "hub")
|
dlt_extra: The dlt extra to install the plugin (e.g., "hub")
|
||||||
|
dlt_version_specifier: Optional version specifier for the plugin. If not provided,
|
||||||
|
reads from dlt's package metadata.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
MissingDependencyException: If version mismatch is detected
|
MissingDependencyException: If version mismatch is detected
|
||||||
"""
|
"""
|
||||||
installed = Version(plugin_version)
|
# Get specifier from dlt's package metadata if not provided
|
||||||
dlt_installed = Version(dlt_version)
|
if dlt_version_specifier is None:
|
||||||
|
from dlt.version import get_dependency_requirement
|
||||||
|
|
||||||
# currently packages must match on minor version
|
req = get_dependency_requirement(pkg_name)
|
||||||
if installed.minor != dlt_installed.minor or (
|
if req is not None:
|
||||||
installed.major != dlt_installed.major and installed.major != 0
|
dlt_version_specifier = req.specifier
|
||||||
):
|
|
||||||
|
# If specifier still not available, exit without checking
|
||||||
|
if dlt_version_specifier is None or len(dlt_version_specifier) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Use specifier.contains() for proper version check (allowing prereleases)
|
||||||
|
if not dlt_version_specifier.contains(plugin_version, prereleases=True):
|
||||||
from dlt.common.exceptions import MissingDependencyException
|
from dlt.common.exceptions import MissingDependencyException
|
||||||
|
|
||||||
custom_msg = (
|
custom_msg = (
|
||||||
f"`{pkg_name}` is a `dlt` plugin and must be installed together with `dlt` with a "
|
f"`{pkg_name}` is a `dlt` plugin and must satisfy version requirement "
|
||||||
f"matching version. `dlt` {dlt_installed.major}.{dlt_installed.minor}.x requires "
|
f"`{dlt_version_specifier}` but you have {plugin_version}. "
|
||||||
f"`{pkg_name}` 0.{dlt_installed.minor}.x but you have "
|
f"Please install the right version of {pkg_name} with:\n\n"
|
||||||
f"{plugin_version}. Please install the right version of {pkg_name} with:\n\n"
|
|
||||||
f'pip install "dlt[{dlt_extra}]=={dlt_version}"\n\n'
|
f'pip install "dlt[{dlt_extra}]=={dlt_version}"\n\n'
|
||||||
"or if you are upgrading the plugin:\n\n"
|
"or if you are upgrading the plugin:\n\n"
|
||||||
f'pip install "dlt[{dlt_extra}]=={dlt_version}" -U {pkg_name}'
|
f'pip install "dlt[{dlt_extra}]=={dlt_version}" -U {pkg_name}'
|
||||||
)
|
)
|
||||||
missing_dep_ex = MissingDependencyException(plugin_module_name, [])
|
missing_dep_ex = MissingDependencyException(plugin_module_name, [])
|
||||||
# ImportError uses `msg` attribute for __str__, not just args
|
|
||||||
missing_dep_ex.args = (custom_msg,)
|
missing_dep_ex.args = (custom_msg,)
|
||||||
missing_dep_ex.msg = custom_msg
|
missing_dep_ex.msg = custom_msg
|
||||||
raise missing_dep_ex
|
raise missing_dep_ex
|
||||||
|
|||||||
@@ -65,10 +65,16 @@ MTIME_DISPATCH = {
|
|||||||
"az": lambda f: ensure_pendulum_datetime_utc(f["last_modified"]),
|
"az": lambda f: ensure_pendulum_datetime_utc(f["last_modified"]),
|
||||||
"gcs": lambda f: ensure_pendulum_datetime_utc(f["updated"]),
|
"gcs": lambda f: ensure_pendulum_datetime_utc(f["updated"]),
|
||||||
"https": lambda f: cast(
|
"https": lambda f: cast(
|
||||||
pendulum.DateTime, pendulum.parse(f["Last-Modified"], exact=True, strict=False)
|
pendulum.DateTime,
|
||||||
|
pendulum.parse(
|
||||||
|
f.get("Last-Modified", pendulum.now().isoformat()), exact=True, strict=False
|
||||||
|
),
|
||||||
),
|
),
|
||||||
"http": lambda f: cast(
|
"http": lambda f: cast(
|
||||||
pendulum.DateTime, pendulum.parse(f["Last-Modified"], exact=True, strict=False)
|
pendulum.DateTime,
|
||||||
|
pendulum.parse(
|
||||||
|
f.get("Last-Modified", pendulum.now().isoformat()), exact=True, strict=False
|
||||||
|
),
|
||||||
),
|
),
|
||||||
"file": lambda f: ensure_pendulum_datetime_utc(f["mtime"]),
|
"file": lambda f: ensure_pendulum_datetime_utc(f["mtime"]),
|
||||||
"memory": lambda f: ensure_pendulum_datetime_utc(f["created"]),
|
"memory": lambda f: ensure_pendulum_datetime_utc(f["created"]),
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from importlib.metadata import version as pkg_version, distribution as pkg_distribution
|
from importlib.metadata import version as pkg_version, distribution as pkg_distribution
|
||||||
|
from typing import Optional
|
||||||
from urllib.request import url2pathname
|
from urllib.request import url2pathname
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
from packaging.requirements import Requirement
|
||||||
|
|
||||||
DLT_IMPORT_NAME = "dlt"
|
DLT_IMPORT_NAME = "dlt"
|
||||||
PKG_NAME = DLT_PKG_NAME = "dlt"
|
PKG_NAME = DLT_PKG_NAME = "dlt"
|
||||||
@@ -30,3 +32,19 @@ def get_installed_requirement_string(
|
|||||||
else:
|
else:
|
||||||
package_requirement = f"{package}{ver_selector}{pkg_version(package)}"
|
package_requirement = f"{package}{ver_selector}{pkg_version(package)}"
|
||||||
return package_requirement
|
return package_requirement
|
||||||
|
|
||||||
|
|
||||||
|
def get_dependency_requirement(
|
||||||
|
dependency_name: str, package: str = DLT_PKG_NAME
|
||||||
|
) -> Optional[Requirement]:
|
||||||
|
"""Find a specific dependency requirement from package metadata"""
|
||||||
|
dist = pkg_distribution(package)
|
||||||
|
|
||||||
|
if dist.requires is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for req_str in dist.requires:
|
||||||
|
req = Requirement(req_str)
|
||||||
|
if req.name == dependency_name:
|
||||||
|
return req
|
||||||
|
return None
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
.PHONY: install-dlthub, update-cli-docs, check-cli-docs
|
.PHONY: update-cli-docs, check-cli-docs, dev
|
||||||
# this must be run from `dlthub_cli` to see workspace commands
|
# this must be run from `dlthub_cli` to see workspace commands
|
||||||
|
# it will use dlthub and dlt-runtime versions from dlt/docs/pyproject.toml to generate docs
|
||||||
|
|
||||||
install-dlthub:
|
dev:
|
||||||
uv pip install dlthub
|
uv sync
|
||||||
|
|
||||||
update-cli-docs: install-dlthub
|
update-cli-docs: dev
|
||||||
uv run dlt --debug render-docs ../../website/docs/hub/command-line-interface.md --commands license workspace profile
|
# generate as there's no license
|
||||||
|
RUNTIME__LICENSE="" uv run dlt --debug render-docs ../../website/docs/hub/command-line-interface.md --commands license workspace profile runtime
|
||||||
|
|
||||||
check-cli-docs: install-dlthub
|
check-cli-docs: dev
|
||||||
uv run dlt --debug render-docs ../../website/docs/hub/command-line-interface.md --compare --commands license workspace profile
|
# generate as there's no license
|
||||||
|
RUNTIME__LICENSE="" uv run dlt --debug render-docs ../../website/docs/hub/command-line-interface.md --compare --commands license workspace profile runtime
|
||||||
|
|||||||
18
docs/uv.lock
generated
18
docs/uv.lock
generated
@@ -834,7 +834,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlt"
|
name = "dlt"
|
||||||
version = "1.20.0a1"
|
version = "1.20.0"
|
||||||
source = { editable = "../" }
|
source = { editable = "../" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "click" },
|
{ name = "click" },
|
||||||
@@ -928,13 +928,13 @@ requires-dist = [
|
|||||||
{ name = "db-dtypes", marker = "extra == 'bigquery'", specifier = ">=1.2.0" },
|
{ name = "db-dtypes", marker = "extra == 'bigquery'", specifier = ">=1.2.0" },
|
||||||
{ name = "db-dtypes", marker = "extra == 'gcp'", specifier = ">=1.2.0" },
|
{ name = "db-dtypes", marker = "extra == 'gcp'", specifier = ">=1.2.0" },
|
||||||
{ name = "deltalake", marker = "extra == 'deltalake'", specifier = ">=0.25.1" },
|
{ name = "deltalake", marker = "extra == 'deltalake'", specifier = ">=0.25.1" },
|
||||||
{ name = "dlt-runtime", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.19.0a0,<0.21" },
|
{ name = "dlt-runtime", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.20.0a0,<0.21" },
|
||||||
{ name = "dlthub", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.20.0a1,<0.21" },
|
{ name = "dlthub", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.20.0a1,<0.21" },
|
||||||
{ name = "duckdb", marker = "extra == 'duckdb'", specifier = ">=0.9" },
|
{ name = "duckdb", marker = "extra == 'duckdb'", specifier = ">=0.9" },
|
||||||
{ name = "duckdb", marker = "extra == 'ducklake'", specifier = ">=1.2.0" },
|
{ name = "duckdb", marker = "extra == 'ducklake'", specifier = ">=1.2.0" },
|
||||||
{ name = "duckdb", marker = "extra == 'motherduck'", specifier = ">=0.9" },
|
{ name = "duckdb", marker = "extra == 'motherduck'", specifier = ">=0.9" },
|
||||||
{ name = "duckdb", marker = "extra == 'workspace'", specifier = ">=0.9" },
|
{ name = "duckdb", marker = "extra == 'workspace'", specifier = ">=0.9" },
|
||||||
{ name = "fsspec", specifier = ">=2025.9.0" },
|
{ name = "fsspec", specifier = ">=2022.4.0" },
|
||||||
{ name = "gcsfs", marker = "extra == 'bigquery'", specifier = ">=2022.4.0" },
|
{ name = "gcsfs", marker = "extra == 'bigquery'", specifier = ">=2022.4.0" },
|
||||||
{ name = "gcsfs", marker = "extra == 'clickhouse'", specifier = ">=2022.4.0" },
|
{ name = "gcsfs", marker = "extra == 'clickhouse'", specifier = ">=2022.4.0" },
|
||||||
{ name = "gcsfs", marker = "extra == 'gcp'", specifier = ">=2022.4.0" },
|
{ name = "gcsfs", marker = "extra == 'gcp'", specifier = ">=2022.4.0" },
|
||||||
@@ -1189,7 +1189,7 @@ requires-dist = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlt-runtime"
|
name = "dlt-runtime"
|
||||||
version = "0.20.0a0"
|
version = "0.20.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "attrs" },
|
{ name = "attrs" },
|
||||||
@@ -1199,22 +1199,22 @@ dependencies = [
|
|||||||
{ name = "python-jose" },
|
{ name = "python-jose" },
|
||||||
{ name = "tabulate" },
|
{ name = "tabulate" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/1d/f5/d5c74ba2560507493b9d5d0c98a8482e15f036f338bb2832730065679e22/dlt_runtime-0.20.0a0.tar.gz", hash = "sha256:3e9d5df91f03152c251e5f874e5a13ac1bd66d5fbac0357c11996bf4e8279c8c", size = 48300, upload-time = "2025-12-04T15:51:51.192Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/d0/86/d7f057d8bdf2f3ada28bf1277b7f24a7abbb221d72788bd682176126a75c/dlt_runtime-0.20.0.tar.gz", hash = "sha256:753c7522bc01c92a453459640e482f87b647b14cc5734d754133a91968acc79f", size = 49532, upload-time = "2025-12-09T14:32:33.708Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/21/1f/ebcfea0c69a697d64f836140bfdb0f73d0be2880547dc00ff267eaad7569/dlt_runtime-0.20.0a0-py3-none-any.whl", hash = "sha256:d6498d4078980c833ea9c5cbfc8b7146488beddb77146ae6d3a2e7d7345dfb5a", size = 118233, upload-time = "2025-12-04T15:51:49.67Z" },
|
{ url = "https://files.pythonhosted.org/packages/4c/b0/02a6c846d89e3c27a592a929d95526036be1d607e48fca214dcbf3b7bf58/dlt_runtime-0.20.0-py3-none-any.whl", hash = "sha256:0969165672b2b3938a618ddd263e0cf8ec356d289253f58134e325e222753056", size = 119573, upload-time = "2025-12-09T14:32:32.119Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlthub"
|
name = "dlthub"
|
||||||
version = "0.20.0a1"
|
version = "0.20.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "python-jose" },
|
{ name = "python-jose" },
|
||||||
{ name = "ruamel-yaml" },
|
{ name = "ruamel-yaml" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/13/20/eb0246c88dd80102a4b02ad807b3459c31855ac0c983f69a2b8fe027a88c/dlthub-0.20.0a1.tar.gz", hash = "sha256:bf8e90bd22bad85ed67d497f97d763678e74a41c70bb3c17e3ae2da7897a0bde", size = 158441, upload-time = "2025-12-07T11:26:45.312Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/77/1b/2c079f22243462e914026172094411ed7ef1fc96c8089e0ca66d1a14038a/dlthub-0.20.1.tar.gz", hash = "sha256:7b3a188abc28601fd4bdf8f17e7925ef729d4f91fb67a6b4eb5c5dc5a04ac3a2", size = 158432, upload-time = "2025-12-09T15:18:10.813Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/40/7b/307126b81ecefbf2dd7569e2da81b2a7b9124dbdcfa6039f3e350bd097c3/dlthub-0.20.0a1-py3-none-any.whl", hash = "sha256:de1a20567da74943931e8fd3551babd345c9f7dcb1f3782d200b308a79c660ce", size = 209794, upload-time = "2025-12-07T11:26:43.808Z" },
|
{ url = "https://files.pythonhosted.org/packages/21/94/b2a87853102c6aa08606b2708d8f678b1e39855e8227fe111e37c32631b6/dlthub-0.20.1-py3-none-any.whl", hash = "sha256:c4d4e0c4515cd68f316ccd02c9ecc007332c861ae6f92a488f7e961935e7f1a0", size = 209767, upload-time = "2025-12-09T15:18:09.067Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "dlt"
|
name = "dlt"
|
||||||
version = "1.20.0a1"
|
version = "1.20.0"
|
||||||
description = "dlt is an open-source python-first scalable data loading library that does not require any backend to run."
|
description = "dlt is an open-source python-first scalable data loading library that does not require any backend to run."
|
||||||
authors = [{ name = "dltHub Inc.", email = "services@dlthub.com" }]
|
authors = [{ name = "dltHub Inc.", email = "services@dlthub.com" }]
|
||||||
requires-python = ">=3.9.2, <3.15"
|
requires-python = ">=3.9.2, <3.15"
|
||||||
@@ -52,7 +52,7 @@ dependencies = [
|
|||||||
"orjson>=3.11.0 ; python_version > '3.13'",
|
"orjson>=3.11.0 ; python_version > '3.13'",
|
||||||
"tenacity>=8.0.2",
|
"tenacity>=8.0.2",
|
||||||
"jsonpath-ng>=1.5.3",
|
"jsonpath-ng>=1.5.3",
|
||||||
"fsspec>=2025.9.0",
|
"fsspec>=2022.4.0",
|
||||||
"packaging>=21.1",
|
"packaging>=21.1",
|
||||||
"pluggy>=1.3.0",
|
"pluggy>=1.3.0",
|
||||||
"win-precise-time>=1.4.2 ; os_name == 'nt' and python_version < '3.13'",
|
"win-precise-time>=1.4.2 ; os_name == 'nt' and python_version < '3.13'",
|
||||||
@@ -189,7 +189,7 @@ workspace = [
|
|||||||
]
|
]
|
||||||
hub = [
|
hub = [
|
||||||
"dlthub>=0.20.0a1,<0.21 ; python_version >= '3.10'",
|
"dlthub>=0.20.0a1,<0.21 ; python_version >= '3.10'",
|
||||||
"dlt-runtime>=0.19.0a0,<0.21 ; python_version >= '3.10'",
|
"dlt-runtime>=0.20.0a0,<0.21 ; python_version >= '3.10'",
|
||||||
]
|
]
|
||||||
|
|
||||||
dbml = [
|
dbml = [
|
||||||
|
|||||||
@@ -174,31 +174,73 @@ def test_context_with_xdg_dir(mocker) -> None:
|
|||||||
|
|
||||||
def test_ensure_plugin_version_match_same_versions() -> None:
|
def test_ensure_plugin_version_match_same_versions() -> None:
|
||||||
"""test that matching versions pass without error."""
|
"""test that matching versions pass without error."""
|
||||||
|
from packaging.specifiers import SpecifierSet
|
||||||
|
|
||||||
|
# Use explicit specifier to test specific version matching scenarios
|
||||||
|
# PEP 440 ordering: .devN < .aN < .bN < .rcN < final < .postN
|
||||||
|
# So we use .dev0 as lower bound to include all pre-releases
|
||||||
|
specifier_1_19 = SpecifierSet(">=1.19.0.dev0,<1.20.0") # includes all prereleases
|
||||||
|
specifier_2_5 = SpecifierSet(">=2.5.0.dev0,<2.6.0")
|
||||||
|
|
||||||
# exact same version
|
# exact same version
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0", "1.19.0", "dlthub", "hub")
|
ensure_plugin_version_match(
|
||||||
ensure_plugin_version_match("dlthub", "1.19.5", "1.19.2", "dlthub", "hub")
|
"fake-plugin", "1.19.0", "1.19.0", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.5", "1.19.2", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
# different patch versions are ok
|
# different patch versions are ok
|
||||||
ensure_plugin_version_match("dlthub", "2.5.0", "2.5.10", "dlthub", "hub")
|
ensure_plugin_version_match(
|
||||||
# alpha specifiers (e.g. 1.19.0a1)
|
"fake-plugin", "2.5.0", "2.5.10", "fake-plugin", "hub", specifier_2_5
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0a1", "1.19.0a2", "dlthub", "hub")
|
)
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0a1", "1.19.0", "dlthub", "hub")
|
# alpha specifiers (e.g. 1.19.0a1) - these are LESS than 1.19.0
|
||||||
# dev specifiers (e.g. 1.19.0.dev1)
|
ensure_plugin_version_match(
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0.dev1", "1.19.0.dev2", "dlthub", "hub")
|
"fake-plugin", "1.19.0a1", "1.19.0a2", "fake-plugin", "hub", specifier_1_19
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0.dev1", "1.19.0", "dlthub", "hub")
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.0a1", "1.19.0", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
|
# dev specifiers (e.g. 1.19.0.dev1) - these are LESS than 1.19.0a0
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.0.dev1", "1.19.0.dev2", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.0.dev1", "1.19.0", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
# post release specifiers
|
# post release specifiers
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0.post1", "1.19.0.post2", "dlthub", "hub")
|
ensure_plugin_version_match(
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0.post1", "1.19.0", "dlthub", "hub")
|
"fake-plugin", "1.19.0.post1", "1.19.0.post2", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.0.post1", "1.19.0", "fake-plugin", "hub", specifier_1_19
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_ensure_plugin_version_match_alpha_plugin() -> None:
|
def test_ensure_plugin_version_match_alpha_plugin() -> None:
|
||||||
"""test that alpha plugins (major=0) match any dlt major version with same minor."""
|
"""test that alpha plugins (major=0) match specifier."""
|
||||||
# alpha plugin (0.x.y) should match dlt 1.x.y with same minor
|
from packaging.specifiers import SpecifierSet
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0", "0.19.0", "dlthub", "hub")
|
|
||||||
ensure_plugin_version_match("dlthub", "1.19.5", "0.19.2", "dlthub", "hub")
|
# specifier for 0.19.x versions (including all pre-releases)
|
||||||
ensure_plugin_version_match("dlthub", "2.19.0", "0.19.0", "dlthub", "hub")
|
# PEP 440 ordering: .devN < .aN < .bN < .rcN < final < .postN
|
||||||
|
specifier_0_19 = SpecifierSet(">=0.19.0.dev0,<0.20.0")
|
||||||
|
|
||||||
|
# alpha plugin (0.x.y) should match specifier
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.0", "0.19.0", "fake-plugin", "hub", specifier_0_19
|
||||||
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.5", "0.19.2", "fake-plugin", "hub", specifier_0_19
|
||||||
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "2.19.0", "0.19.0", "fake-plugin", "hub", specifier_0_19
|
||||||
|
)
|
||||||
# alpha plugin with alpha/dev specifiers
|
# alpha plugin with alpha/dev specifiers
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0a1", "0.19.0a2", "dlthub", "hub")
|
ensure_plugin_version_match(
|
||||||
ensure_plugin_version_match("dlthub", "1.19.0.dev1", "0.19.0.dev2", "dlthub", "hub")
|
"fake-plugin", "1.19.0a1", "0.19.0a2", "fake-plugin", "hub", specifier_0_19
|
||||||
|
)
|
||||||
|
ensure_plugin_version_match(
|
||||||
|
"fake-plugin", "1.19.0.dev1", "0.19.0.dev2", "fake-plugin", "hub", specifier_0_19
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -217,6 +259,13 @@ def test_ensure_plugin_version_match_alpha_plugin() -> None:
|
|||||||
)
|
)
|
||||||
def test_ensure_plugin_version_match_mismatch(dlt_version: str, plugin_version: str) -> None:
|
def test_ensure_plugin_version_match_mismatch(dlt_version: str, plugin_version: str) -> None:
|
||||||
"""test that mismatched versions raise MissingDependencyException."""
|
"""test that mismatched versions raise MissingDependencyException."""
|
||||||
|
from packaging.specifiers import SpecifierSet
|
||||||
|
|
||||||
|
# Use explicit specifier that requires 1.19.x versions
|
||||||
|
specifier = SpecifierSet(">=1.19.0,<1.20.0")
|
||||||
|
|
||||||
with pytest.raises(MissingDependencyException) as exc_info:
|
with pytest.raises(MissingDependencyException) as exc_info:
|
||||||
ensure_plugin_version_match("dlthub", dlt_version, plugin_version, "dlthub", "hub")
|
ensure_plugin_version_match(
|
||||||
assert "dlthub" in str(exc_info.value)
|
"fake-plugin", dlt_version, plugin_version, "fake-plugin", "hub", specifier
|
||||||
|
)
|
||||||
|
assert "fake-plugin" in str(exc_info.value)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
from importlib.metadata import PackageNotFoundError
|
from importlib.metadata import PackageNotFoundError
|
||||||
|
from packaging.requirements import Requirement
|
||||||
|
|
||||||
from dlt.version import get_installed_requirement_string
|
from dlt.version import get_installed_requirement_string, get_dependency_requirement
|
||||||
|
|
||||||
|
|
||||||
def test_installed_requirement_string() -> None:
|
def test_installed_requirement_string() -> None:
|
||||||
@@ -15,3 +16,24 @@ def test_installed_requirement_string() -> None:
|
|||||||
# this is not installed
|
# this is not installed
|
||||||
with pytest.raises(PackageNotFoundError):
|
with pytest.raises(PackageNotFoundError):
|
||||||
get_installed_requirement_string("requests-X")
|
get_installed_requirement_string("requests-X")
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_dependency_requirement() -> None:
|
||||||
|
# dlt depends on dlthub, so this should return a Requirement
|
||||||
|
req = get_dependency_requirement("dlthub")
|
||||||
|
assert req is not None
|
||||||
|
assert isinstance(req, Requirement)
|
||||||
|
assert req.name == "dlthub"
|
||||||
|
# click has a version specifier
|
||||||
|
assert str(req.specifier) != ""
|
||||||
|
|
||||||
|
# dlt depends on fsspec with a version constraint
|
||||||
|
req = get_dependency_requirement("fsspec")
|
||||||
|
assert req is not None
|
||||||
|
assert req.name == "fsspec"
|
||||||
|
# verify we can check version satisfaction
|
||||||
|
assert "2022.4.0" in req.specifier
|
||||||
|
|
||||||
|
# non-existent dependency returns None
|
||||||
|
req = get_dependency_requirement("non-existent-package-xyz")
|
||||||
|
assert req is None
|
||||||
|
|||||||
@@ -4463,14 +4463,14 @@ def test_pending_package_exception_warning() -> None:
|
|||||||
with pytest.raises(PipelineStepFailed) as pip_ex:
|
with pytest.raises(PipelineStepFailed) as pip_ex:
|
||||||
pipeline.run()
|
pipeline.run()
|
||||||
|
|
||||||
# none of the jobs passed so we have pending package but not partial
|
# one of the job failed and package is aborted. sometimes the other
|
||||||
|
# job completed, sometimes is still pending so we disable pending test
|
||||||
assert pip_ex.value.step == "load"
|
assert pip_ex.value.step == "load"
|
||||||
print(str(pip_ex.value))
|
# assert "Pending packages" not in str(pip_ex.value)
|
||||||
assert "Pending packages" not in str(pip_ex.value)
|
|
||||||
assert "partially loaded" in str(pip_ex.value)
|
assert "partially loaded" in str(pip_ex.value)
|
||||||
assert pip_ex.value.load_id is not None
|
assert pip_ex.value.load_id is not None
|
||||||
assert pip_ex.value.is_package_partially_loaded is True
|
assert pip_ex.value.is_package_partially_loaded is True
|
||||||
assert pip_ex.value.has_pending_data is False
|
# assert pip_ex.value.has_pending_data is False
|
||||||
|
|
||||||
|
|
||||||
def test_cleanup() -> None:
|
def test_cleanup() -> None:
|
||||||
|
|||||||
18
uv.lock
generated
18
uv.lock
generated
@@ -2058,7 +2058,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlt"
|
name = "dlt"
|
||||||
version = "1.20.0a1"
|
version = "1.20.0"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "click" },
|
{ name = "click" },
|
||||||
@@ -2356,13 +2356,13 @@ requires-dist = [
|
|||||||
{ name = "db-dtypes", marker = "extra == 'bigquery'", specifier = ">=1.2.0" },
|
{ name = "db-dtypes", marker = "extra == 'bigquery'", specifier = ">=1.2.0" },
|
||||||
{ name = "db-dtypes", marker = "extra == 'gcp'", specifier = ">=1.2.0" },
|
{ name = "db-dtypes", marker = "extra == 'gcp'", specifier = ">=1.2.0" },
|
||||||
{ name = "deltalake", marker = "extra == 'deltalake'", specifier = ">=0.25.1" },
|
{ name = "deltalake", marker = "extra == 'deltalake'", specifier = ">=0.25.1" },
|
||||||
{ name = "dlt-runtime", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.19.0a0,<0.21" },
|
{ name = "dlt-runtime", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.20.0a0,<0.21" },
|
||||||
{ name = "dlthub", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.20.0a1,<0.21" },
|
{ name = "dlthub", marker = "python_full_version >= '3.10' and extra == 'hub'", specifier = ">=0.20.0a1,<0.21" },
|
||||||
{ name = "duckdb", marker = "extra == 'duckdb'", specifier = ">=0.9" },
|
{ name = "duckdb", marker = "extra == 'duckdb'", specifier = ">=0.9" },
|
||||||
{ name = "duckdb", marker = "extra == 'ducklake'", specifier = ">=1.2.0" },
|
{ name = "duckdb", marker = "extra == 'ducklake'", specifier = ">=1.2.0" },
|
||||||
{ name = "duckdb", marker = "extra == 'motherduck'", specifier = ">=0.9" },
|
{ name = "duckdb", marker = "extra == 'motherduck'", specifier = ">=0.9" },
|
||||||
{ name = "duckdb", marker = "extra == 'workspace'", specifier = ">=0.9" },
|
{ name = "duckdb", marker = "extra == 'workspace'", specifier = ">=0.9" },
|
||||||
{ name = "fsspec", specifier = ">=2025.9.0" },
|
{ name = "fsspec", specifier = ">=2022.4.0" },
|
||||||
{ name = "gcsfs", marker = "extra == 'bigquery'", specifier = ">=2022.4.0" },
|
{ name = "gcsfs", marker = "extra == 'bigquery'", specifier = ">=2022.4.0" },
|
||||||
{ name = "gcsfs", marker = "extra == 'clickhouse'", specifier = ">=2022.4.0" },
|
{ name = "gcsfs", marker = "extra == 'clickhouse'", specifier = ">=2022.4.0" },
|
||||||
{ name = "gcsfs", marker = "extra == 'gcp'", specifier = ">=2022.4.0" },
|
{ name = "gcsfs", marker = "extra == 'gcp'", specifier = ">=2022.4.0" },
|
||||||
@@ -2535,7 +2535,7 @@ streamlit = [{ name = "streamlit", marker = "python_full_version >= '3.9' and py
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlt-runtime"
|
name = "dlt-runtime"
|
||||||
version = "0.20.0a0"
|
version = "0.20.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "attrs", version = "25.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
{ name = "attrs", version = "25.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
||||||
@@ -2545,22 +2545,22 @@ dependencies = [
|
|||||||
{ name = "python-jose", marker = "python_full_version >= '3.10'" },
|
{ name = "python-jose", marker = "python_full_version >= '3.10'" },
|
||||||
{ name = "tabulate", marker = "python_full_version >= '3.10'" },
|
{ name = "tabulate", marker = "python_full_version >= '3.10'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/1d/f5/d5c74ba2560507493b9d5d0c98a8482e15f036f338bb2832730065679e22/dlt_runtime-0.20.0a0.tar.gz", hash = "sha256:3e9d5df91f03152c251e5f874e5a13ac1bd66d5fbac0357c11996bf4e8279c8c", size = 48300, upload-time = "2025-12-04T15:51:51.192Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/d0/86/d7f057d8bdf2f3ada28bf1277b7f24a7abbb221d72788bd682176126a75c/dlt_runtime-0.20.0.tar.gz", hash = "sha256:753c7522bc01c92a453459640e482f87b647b14cc5734d754133a91968acc79f", size = 49532, upload-time = "2025-12-09T14:32:33.708Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/21/1f/ebcfea0c69a697d64f836140bfdb0f73d0be2880547dc00ff267eaad7569/dlt_runtime-0.20.0a0-py3-none-any.whl", hash = "sha256:d6498d4078980c833ea9c5cbfc8b7146488beddb77146ae6d3a2e7d7345dfb5a", size = 118233, upload-time = "2025-12-04T15:51:49.67Z" },
|
{ url = "https://files.pythonhosted.org/packages/4c/b0/02a6c846d89e3c27a592a929d95526036be1d607e48fca214dcbf3b7bf58/dlt_runtime-0.20.0-py3-none-any.whl", hash = "sha256:0969165672b2b3938a618ddd263e0cf8ec356d289253f58134e325e222753056", size = 119573, upload-time = "2025-12-09T14:32:32.119Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlthub"
|
name = "dlthub"
|
||||||
version = "0.20.0a1"
|
version = "0.20.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "python-jose", marker = "python_full_version >= '3.10'" },
|
{ name = "python-jose", marker = "python_full_version >= '3.10'" },
|
||||||
{ name = "ruamel-yaml", marker = "python_full_version >= '3.10'" },
|
{ name = "ruamel-yaml", marker = "python_full_version >= '3.10'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/13/20/eb0246c88dd80102a4b02ad807b3459c31855ac0c983f69a2b8fe027a88c/dlthub-0.20.0a1.tar.gz", hash = "sha256:bf8e90bd22bad85ed67d497f97d763678e74a41c70bb3c17e3ae2da7897a0bde", size = 158441, upload-time = "2025-12-07T11:26:45.312Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/77/1b/2c079f22243462e914026172094411ed7ef1fc96c8089e0ca66d1a14038a/dlthub-0.20.1.tar.gz", hash = "sha256:7b3a188abc28601fd4bdf8f17e7925ef729d4f91fb67a6b4eb5c5dc5a04ac3a2", size = 158432, upload-time = "2025-12-09T15:18:10.813Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/40/7b/307126b81ecefbf2dd7569e2da81b2a7b9124dbdcfa6039f3e350bd097c3/dlthub-0.20.0a1-py3-none-any.whl", hash = "sha256:de1a20567da74943931e8fd3551babd345c9f7dcb1f3782d200b308a79c660ce", size = 209794, upload-time = "2025-12-07T11:26:43.808Z" },
|
{ url = "https://files.pythonhosted.org/packages/21/94/b2a87853102c6aa08606b2708d8f678b1e39855e8227fe111e37c32631b6/dlthub-0.20.1-py3-none-any.whl", hash = "sha256:c4d4e0c4515cd68f316ccd02c9ecc007332c861ae6f92a488f7e961935e7f1a0", size = 209767, upload-time = "2025-12-09T15:18:09.067Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Reference in New Issue
Block a user