From c84f203466ed63096a5db25a23beb84653d7f8e8 Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 12:34:02 +0200 Subject: [PATCH 1/9] Add GH action for docs building --- .github/workflows/docs-build-check.yml | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/docs-build-check.yml diff --git a/.github/workflows/docs-build-check.yml b/.github/workflows/docs-build-check.yml new file mode 100644 index 00000000..f416876c --- /dev/null +++ b/.github/workflows/docs-build-check.yml @@ -0,0 +1,36 @@ +name: Docs Build Check + +on: + pull_request: + branches: + - main + +jobs: + docs-build: + name: Check Sphinx docs build + runs-on: ubuntu-latest + + defaults: + run: + working-directory: "./docs" + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: Install client and dependencies + working-directory: "./" + run: | + python -m pip install --upgrade pip setuptools + pip install . + + - name: Install docs dependencies + run: | + pip install -r requirements-docs.txt + + - name: Build documentation + run: SPHINXOPTS="-W" make html From 32b3cd180e956d2d3d02a8e6f87d7cdff2b3cb33 Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 12:39:29 +0200 Subject: [PATCH 2/9] Consolidate docs build and publish actions --- .github/workflows/docs-build-check.yml | 36 --------------------- .github/workflows/docs-publish.yml | 45 ++++++++++++++++++-------- 2 files changed, 32 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/docs-build-check.yml diff --git a/.github/workflows/docs-build-check.yml b/.github/workflows/docs-build-check.yml deleted file mode 100644 index f416876c..00000000 --- a/.github/workflows/docs-build-check.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Docs Build Check - -on: - pull_request: - branches: - - main - -jobs: - docs-build: - name: Check Sphinx docs build - runs-on: ubuntu-latest - - defaults: - run: - working-directory: "./docs" - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.x" - - - name: Install client and dependencies - working-directory: "./" - run: | - python -m pip install --upgrade pip setuptools - pip install . - - - name: Install docs dependencies - run: | - pip install -r requirements-docs.txt - - - name: Build documentation - run: SPHINXOPTS="-W" make html diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml index 663916ae..bf60638e 100644 --- a/.github/workflows/docs-publish.yml +++ b/.github/workflows/docs-publish.yml @@ -1,13 +1,16 @@ -name: Publish Docs +name: Docs on: workflow_dispatch: release: types: [published] + pull_request: + branches: + - main jobs: - deploy: - + build: + name: Build documentation runs-on: ubuntu-latest defaults: @@ -21,22 +24,39 @@ jobs: uses: actions/setup-python@v4 with: python-version: "3.x" + - name: Install client and dependencies working-directory: "./" run: | python -m pip install --upgrade pip setuptools pip install . + - name: Install docs dependencies run: | pip install -r requirements-docs.txt + - name: Build documentation - run: make html + run: SPHINXOPTS="-W" make html -# - name: Upload docs as artifact -# uses: actions/upload-artifact@v3 -# with: -# name: docs -# path: docs/build + - name: Upload build artifact + if: github.event_name == 'release' || github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: docs-html + path: docs/build/html + + deploy: + name: Deploy documentation + needs: build + if: github.event_name == 'release' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + + steps: + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: docs-html + path: docs-html - name: Authenticate with Google uses: "google-github-actions/auth@v2" @@ -44,16 +64,15 @@ jobs: project_id: ${{ secrets.GCS_PROJECT }} credentials_json: ${{ secrets.GCS_SERVICE_ACCOUNT_ACCESS_KEY }} - - name: 'Set up Cloud SDK' - uses: 'google-github-actions/setup-gcloud@v2' + - name: Set up Cloud SDK + uses: "google-github-actions/setup-gcloud@v2" - name: Upload to Google Cloud Storage env: UPLOAD_PATH: ${{ format('gs://{0}/docs/client', secrets.DOCS_BUCKET) }} - run: gsutil -m rsync -d -r build/html $UPLOAD_PATH + run: gsutil -m rsync -d -r docs-html $UPLOAD_PATH - name: Invalidate CDN Cache env: LOAD_BALANCER: ${{ secrets.LOAD_BALANCER_NAME }} run: gcloud compute url-maps invalidate-cdn-cache $LOAD_BALANCER --async --path "/docs/client/*" - From 14344a86b604e5f4b713e9a79bb0aa3cca89371c Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 12:45:46 +0200 Subject: [PATCH 3/9] Upgrade setup-python GH action to current upstream latest (v6) --- .github/workflows/docs-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml index bf60638e..2edf997d 100644 --- a/.github/workflows/docs-publish.yml +++ b/.github/workflows/docs-publish.yml @@ -3,7 +3,7 @@ name: Docs on: workflow_dispatch: release: - types: [published] + types: [ published ] pull_request: branches: - main @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v6 with: python-version: "3.x" From 8044e1b6107f232935dc1c618bf35c972912860f Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 14:24:44 +0200 Subject: [PATCH 4/9] Remove unnecessary pytz dependency --- dagshub/data_engine/model/query.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dagshub/data_engine/model/query.py b/dagshub/data_engine/model/query.py index dbf5b208..6d7054cb 100644 --- a/dagshub/data_engine/model/query.py +++ b/dagshub/data_engine/model/query.py @@ -2,14 +2,13 @@ import enum import logging import uuid -from typing import Optional, Union, Dict +from typing import Dict, Optional, Union -import pytz -from treelib import Tree, Node +from treelib import Node, Tree +from dagshub.data_engine.dtypes import MetadataFieldType from dagshub.data_engine.model.errors import WrongOperatorError from dagshub.data_engine.model.schema_util import metadata_type_lookup, metadata_type_lookup_reverse -from dagshub.data_engine.dtypes import MetadataFieldType logger = logging.getLogger(__name__) @@ -24,7 +23,7 @@ def bytes_deserializer(val: str) -> bytes: _metadataTypeCustomConverters = { bool: lambda x: x.lower() == "true", bytes: bytes_deserializer, - datetime.datetime: lambda x: datetime.datetime.fromtimestamp(int(x) / 1000).astimezone(pytz.utc), + datetime.datetime: lambda x: datetime.datetime.fromtimestamp(int(x) / 1000, tz=datetime.timezone.utc), } From e30a34b5a4885cf7ce93104c37468fe4e7f9267d Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 14:48:53 +0200 Subject: [PATCH 5/9] Upgrade doc package versions, add mocks --- docs/Makefile | 4 ++-- docs/requirements-docs.txt | 12 ++++++------ docs/source/conf.py | 8 +++++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index f1887064..db2d128f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -18,7 +18,7 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --exception-on-warning -W serve: - sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --watch "$(CODEDIR)" $(O) + sphinx-autobuild -W "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --watch "$(CODEDIR)" $(O) diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 8d2a7352..1f9294cb 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,7 +1,7 @@ -sphinx==7.3.7 -furo==2024.5.6 -sphinx-autobuild==2024.4.16 +sphinx==9.1.0 +furo==2025.12.19 +sphinx-autobuild==2025.8.25 sphinx-copybutton==0.5.2 -sphinx-sitemap==2.6.0 -sphinx-click==5.0.1 -sphinx-autodoc-typehints==2.3.0 +sphinx-sitemap==2.9.0 +sphinx-click==6.2.0 +sphinx-autodoc-typehints==3.9.9 diff --git a/docs/source/conf.py b/docs/source/conf.py index 733479a5..87cbb833 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -8,12 +8,18 @@ import os import sys +from unittest import mock project_root = os.path.join(__file__, "../../..") sys.path.insert(0, os.path.abspath(project_root)) +# Python modules that don't get installed in the doc build environment due to heaviness, so they get mocked +MOCK_MODULES = ["mlflow", "mlflow.artifacts", "fiftyone", "datasets", "tensorflow", "IPython"] +for mod_name in MOCK_MODULES: + sys.modules[mod_name] = mock.Mock() + project = "DagsHub Client" -copyright = "2023, DagsHub" +copyright = "2026, DagsHub" author = "DagsHub" # -- General configuration --------------------------------------------------- From a0ae61fdc3e1a6cdb08bfb9f3b09e1d5e9bd059b Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 14:56:00 +0200 Subject: [PATCH 6/9] Fix mocks --- docs/source/conf.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 87cbb833..f635d77e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,6 +6,7 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import importlib.machinery import os import sys from unittest import mock @@ -13,10 +14,29 @@ project_root = os.path.join(__file__, "../../..") sys.path.insert(0, os.path.abspath(project_root)) -# Python modules that don't get installed in the doc build environment due to heaviness, so they get mocked -MOCK_MODULES = ["mlflow", "mlflow.artifacts", "fiftyone", "datasets", "tensorflow", "IPython"] +# Python modules that don't get installed in the doc build environment due to heaviness, so they get mocked. +# Each mock needs a real ModuleSpec so that importlib.util.find_spec() doesn't raise ValueError. +MOCK_MODULES = [ + "mlflow", + "mlflow.artifacts", + "mlflow.entities", + "fiftyone", + "datasets", + "tensorflow", + "IPython", +] for mod_name in MOCK_MODULES: - sys.modules[mod_name] = mock.Mock() + spec = importlib.machinery.ModuleSpec(mod_name, None) + pkg = mod_name.rsplit(".", 1)[0] if "." in mod_name else mod_name + mod = mock.MagicMock( + __spec__=spec, __name__=mod_name, __path__=[], __file__=None, __loader__=None, __package__=pkg, + ) + sys.modules[mod_name] = mod + parts = mod_name.split(".") + if len(parts) > 1: + parent = sys.modules.get(parts[0]) + if parent is not None: + setattr(parent, parts[-1], mod) project = "DagsHub Client" copyright = "2026, DagsHub" From 33fbf74cdc67d3533cd0ec48e6f85a6a674d05c8 Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 14:59:49 +0200 Subject: [PATCH 7/9] Doc formatting change --- dagshub/common/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dagshub/common/cli.py b/dagshub/common/cli.py index 1a5b2772..e5bafe67 100644 --- a/dagshub/common/cli.py +++ b/dagshub/common/cli.py @@ -339,7 +339,7 @@ def create(ctx, repo_name, upload_data, clone, verbose, quiet): create a repo and optionally: - upload files to 'data' from a URL dir using `-u` flag. .zip and .tar files are extracted, - other formats copied as is. + other formats copied as is. - clone the repo locally using `--clone` flag From 93fb3e6e248b5361033e63fededc23cc1f53cfbc Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 15:22:58 +0200 Subject: [PATCH 8/9] Fix documentation problems, hopefully all of them --- .../annotation/voxel_conversion.py | 17 ++++++----- docs/source/conf.py | 30 ++++--------------- docs/source/reference/metric_logging.rst | 2 ++ 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/dagshub/data_engine/annotation/voxel_conversion.py b/dagshub/data_engine/annotation/voxel_conversion.py index e3474af5..b5a86d70 100644 --- a/dagshub/data_engine/annotation/voxel_conversion.py +++ b/dagshub/data_engine/annotation/voxel_conversion.py @@ -3,13 +3,14 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from dagshub.data_engine.client.models import Datapoint - import fiftyone as fo + import fiftyone + + from dagshub.data_engine.model.datapoint import Datapoint logger = logging.getLogger(__name__) -def add_voxel_annotations(sample: "fo.Sample", datapoint: "Datapoint", *annotation_fields: str): +def add_voxel_annotations(sample: "fiftyone.Sample", datapoint: "Datapoint", *annotation_fields: str): """ Adds annotation to the voxel sample. @@ -26,7 +27,7 @@ def add_voxel_annotations(sample: "fo.Sample", datapoint: "Datapoint", *annotati sample.add_labels(label, label_field=field) -def add_ls_annotations(sample: "fo.Sample", datapoint: "Datapoint", *annotation_fields: str): +def add_ls_annotations(sample: "fiftyone.Sample", datapoint: "Datapoint", *annotation_fields: str): """ Adds LabelStudio annotation to the voxel sample. @@ -35,17 +36,17 @@ def add_ls_annotations(sample: "fo.Sample", datapoint: "Datapoint", *annotation_ datapoint: Data Engine datapoint to get metadata from annotation_fields: fields from which to get annotations """ - from fiftyone.utils.labelstudio import import_label_studio_annotation from fiftyone import ( - Detections, - Detection, Classification, Classifications, + Detection, + Detections, Keypoint, Keypoints, - Polylines, Polyline, + Polylines, ) + from fiftyone.utils.labelstudio import import_label_studio_annotation for field in annotation_fields: annotations = datapoint.metadata.get(field) diff --git a/docs/source/conf.py b/docs/source/conf.py index f635d77e..0c7ef098 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,37 +6,17 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -import importlib.machinery import os import sys -from unittest import mock +import types project_root = os.path.join(__file__, "../../..") sys.path.insert(0, os.path.abspath(project_root)) -# Python modules that don't get installed in the doc build environment due to heaviness, so they get mocked. -# Each mock needs a real ModuleSpec so that importlib.util.find_spec() doesn't raise ValueError. -MOCK_MODULES = [ - "mlflow", - "mlflow.artifacts", - "mlflow.entities", - "fiftyone", - "datasets", - "tensorflow", - "IPython", -] -for mod_name in MOCK_MODULES: - spec = importlib.machinery.ModuleSpec(mod_name, None) - pkg = mod_name.rsplit(".", 1)[0] if "." in mod_name else mod_name - mod = mock.MagicMock( - __spec__=spec, __name__=mod_name, __path__=[], __file__=None, __loader__=None, __package__=pkg, - ) - sys.modules[mod_name] = mod - parts = mod_name.split(".") - if len(parts) > 1: - parent = sys.modules.get(parts[0]) - if parent is not None: - setattr(parent, parts[-1], mod) +# Fix for is_mlflow_installed reading the spec of the module that is not imported in the doc build environment +_env_mod = types.ModuleType("dagshub.common.environment") +_env_mod.is_mlflow_installed = False +sys.modules["dagshub.common.environment"] = _env_mod project = "DagsHub Client" copyright = "2026, DagsHub" diff --git a/docs/source/reference/metric_logging.rst b/docs/source/reference/metric_logging.rst index 12e35533..9245b317 100644 --- a/docs/source/reference/metric_logging.rst +++ b/docs/source/reference/metric_logging.rst @@ -1,3 +1,5 @@ +:orphan: + Metric Logging (``dagshub.logger``) ==================================== From b93880eda85f61bba391d53f34a964f442c1d2a4 Mon Sep 17 00:00:00 2001 From: Kirill Bolashev Date: Mon, 23 Mar 2026 15:26:33 +0200 Subject: [PATCH 9/9] Use build machine's year for copyright --- docs/source/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 0c7ef098..e3b56b91 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -9,6 +9,7 @@ import os import sys import types +from datetime import datetime project_root = os.path.join(__file__, "../../..") sys.path.insert(0, os.path.abspath(project_root)) @@ -19,7 +20,7 @@ sys.modules["dagshub.common.environment"] = _env_mod project = "DagsHub Client" -copyright = "2026, DagsHub" +copyright = f"{datetime.now().year}, DagsHub" author = "DagsHub" # -- General configuration ---------------------------------------------------