From 5648323687dc3bc11dcafef1c8af5a5df447b767 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Mon, 23 Jun 2025 15:57:30 -0700 Subject: [PATCH 01/25] Initial commit for mkdocs --- python/docs/index.md | 28 ++++++++++ .../lib/sift_client/_internal/sync_wrapper.py | 10 ++++ python/lib/sift_client/resources/py.typed | 1 + .../resources/sync_stubs/__init__.py | 7 +++ python/lib/sift_client/types/asset.py | 7 +++ python/mkdocs.yml | 55 +++++++++++++++++++ python/pyproject.toml | 2 + 7 files changed, 110 insertions(+) create mode 100644 python/docs/index.md create mode 100644 python/lib/sift_client/resources/py.typed create mode 100644 python/mkdocs.yml diff --git a/python/docs/index.md b/python/docs/index.md new file mode 100644 index 000000000..290487123 --- /dev/null +++ b/python/docs/index.md @@ -0,0 +1,28 @@ +# Welcome to MkDocs + +For full documentation visit [mkdocs.org](https://www.mkdocs.org). + +## Commands + +* `mkdocs new [dir-name]` - Create a new project. +* `mkdocs serve` - Start the live-reloading docs server. +* `mkdocs build` - Build the documentation site. +* `mkdocs -h` - Print help message and exit. + +## Project layout + + mkdocs.yml # The configuration file. + docs/ + index.md # The documentation homepage. + ... # Other markdown pages, images and other files. + +# Reference + +## Client + +::: sift_client.client.SiftClient + +## Sync APIs + +::: sift_client.resources.AssetsAPI +::: sift_client.resources.PingAPI \ No newline at end of file diff --git a/python/lib/sift_client/_internal/sync_wrapper.py b/python/lib/sift_client/_internal/sync_wrapper.py index 569cab0f9..323f60c3e 100644 --- a/python/lib/sift_client/_internal/sync_wrapper.py +++ b/python/lib/sift_client/_internal/sync_wrapper.py @@ -6,6 +6,7 @@ import asyncio import inspect +import sys from functools import wraps from typing import Any, Type, TypeVar @@ -61,6 +62,7 @@ def _run(self, coro): "__doc__": f"Sync counterpart to `{name}`.\n\n{cls.__doc__ or ''}", "__init__": __init__, "_run": _run, + "__qualname__": sync_name, # Add __qualname__ to help static analyzers } # helper to wrap an async method and make into a sync method @@ -134,7 +136,15 @@ def sync_prop(self, _prop_name=prop_name): namespace[name] = _wrap_sync(name) + # Create the sync class sync_class = type(sync_name, (object,), namespace) # noqa + + # Register the class in the module's globals + # This helps static analysis tools recognize it as a proper class + if module in sys.modules: + module_globals = sys.modules[module].__dict__ + module_globals[sync_name] = sync_class + _registered.append(SyncAPIRegistration(async_cls=cls, sync_cls=sync_class)) return sync_class diff --git a/python/lib/sift_client/resources/py.typed b/python/lib/sift_client/resources/py.typed new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/python/lib/sift_client/resources/py.typed @@ -0,0 +1 @@ + diff --git a/python/lib/sift_client/resources/sync_stubs/__init__.py b/python/lib/sift_client/resources/sync_stubs/__init__.py index 53628cb13..947966772 100644 --- a/python/lib/sift_client/resources/sync_stubs/__init__.py +++ b/python/lib/sift_client/resources/sync_stubs/__init__.py @@ -15,3 +15,10 @@ AssetsAPI = generate_sync_api(AssetsAPIAsync, "AssetsAPI") CalculatedChannelsAPI = generate_sync_api(CalculatedChannelsAPIAsync, "CalculatedChannelsAPI") RunsAPI = generate_sync_api(RunsAPIAsync, "RunsAPI") + +__all__ = [ + "PingAPI", + "AssetsAPI", + "CalculatedChannelsAPI", + "RunsAPI" +] diff --git a/python/lib/sift_client/types/asset.py b/python/lib/sift_client/types/asset.py index e063430fc..610200820 100644 --- a/python/lib/sift_client/types/asset.py +++ b/python/lib/sift_client/types/asset.py @@ -3,6 +3,7 @@ from datetime import datetime from typing import TYPE_CHECKING, Type +from pydantic import BaseModel from sift.assets.v1.assets_pb2 import Asset as AssetProto from sift_client.types._base import BaseType, MappingHelper, ModelUpdate @@ -12,6 +13,12 @@ from sift_client.client import SiftClient +class Test(BaseModel): + """Model of a test.""" + + name: str + + class Asset(BaseType[AssetProto, "Asset"]): """ Model of the Sift Asset. diff --git a/python/mkdocs.yml b/python/mkdocs.yml new file mode 100644 index 000000000..f89945682 --- /dev/null +++ b/python/mkdocs.yml @@ -0,0 +1,55 @@ +site_name: Sift Python Client Library +repo_url: https://github.com/sift-stack/sift/tree/main/python +theme: + name: material + +nav: + - Home: index.md + - API: sync_apis.md + +plugins: + - search + - autorefs + - mkdocstrings: + default_handler: python + handlers: + python: + options: + load_external_modules: true + show_source: false + allow_inspection: true + find_stubs_package: true + show_if_no_docstring: false + # TODO: custom griffe plugin instead + force_inspection: true # Needed for run-time generated sync_stubs + filters: [ "!^__", "!^_abc_", "!^_", "!TYPE_CHECKING" ] + # Explicitly include stubs directory + search_path: [ "../lib" ] + # Styling + group_by_category: true + docstring_section_style: spacy + docstring_style: "google" + heading_level: 1 + merge_init_into_class: true + separate_signature: true + show_root_heading: true + show_signature_annotations: true + signature_crossrefs: true + show_symbol_type_heading: true + show_symbol_type_toc: true + summary: true + # Disabled until custom griffe plugin otherwise fails due to force_inspection + # extensions: + # - griffe_pydantic: + # schema: true + + - api-autonav: + modules: [ lib/sift_client ] #, lib/sift_py, lib/sift ] + exclude_private: true + nav_item_prefix: "" + module_options: + # special filters to avoid rendering the async again + sift_client.resources.sync_stubs: + filters: [ "!Async$", "!^__", "!^_abc_", "!^generate" ] + + diff --git a/python/pyproject.toml b/python/pyproject.toml index c55580b85..9ac9a8292 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -55,11 +55,13 @@ development = [ "ruff", ] build = ["pdoc==14.5.0", "build==1.2.1"] +docs = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mkdocs-include-markdown-plugin"] openssl = ["pyOpenSSL<24.0.0", "types-pyOpenSSL<24.0.0", "cffi~=1.14"] tdms = ["npTDMS~=1.9"] rosbags = ["rosbags~=0.0"] hdf5 = ["h5py~=3.11", "polars~=1.8"] + [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" From 78f2307c9d1abb17605c5480d9aa97c29d798e87 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 26 Jun 2025 15:16:58 -0700 Subject: [PATCH 02/25] iterating on usage of __all__ --- python/lib/sift_client/__init__.py | 5 ----- python/lib/sift_client/types/asset.py | 7 ------- python/mkdocs.yml | 10 ++++++---- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/python/lib/sift_client/__init__.py b/python/lib/sift_client/__init__.py index 7589627f7..928b6dc31 100644 --- a/python/lib/sift_client/__init__.py +++ b/python/lib/sift_client/__init__.py @@ -1,7 +1,2 @@ from sift_client.client import SiftClient from sift_client.transport import SiftConnectionConfig - -__all__ = [ - "SiftClient", - "SiftConnectionConfig", -] diff --git a/python/lib/sift_client/types/asset.py b/python/lib/sift_client/types/asset.py index 610200820..e063430fc 100644 --- a/python/lib/sift_client/types/asset.py +++ b/python/lib/sift_client/types/asset.py @@ -3,7 +3,6 @@ from datetime import datetime from typing import TYPE_CHECKING, Type -from pydantic import BaseModel from sift.assets.v1.assets_pb2 import Asset as AssetProto from sift_client.types._base import BaseType, MappingHelper, ModelUpdate @@ -13,12 +12,6 @@ from sift_client.client import SiftClient -class Test(BaseModel): - """Model of a test.""" - - name: str - - class Asset(BaseType[AssetProto, "Asset"]): """ Model of the Sift Asset. diff --git a/python/mkdocs.yml b/python/mkdocs.yml index f89945682..ef31c78a3 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -19,10 +19,12 @@ plugins: show_source: false allow_inspection: true find_stubs_package: true - show_if_no_docstring: false + show_if_no_docstring: true # TODO: custom griffe plugin instead - force_inspection: true # Needed for run-time generated sync_stubs - filters: [ "!^__", "!^_abc_", "!^_", "!TYPE_CHECKING" ] + # force_inspection: true # Needed for run-time generated sync_stubs + # filters: [ "!^__", "!^_abc_", "!^_", "!TYPE_CHECKING" ] + filters: "public" + show_submodules: false # Explicitly include stubs directory search_path: [ "../lib" ] # Styling @@ -44,7 +46,7 @@ plugins: # schema: true - api-autonav: - modules: [ lib/sift_client ] #, lib/sift_py, lib/sift ] + modules: [ lib/sift_client ] #, lib/sift ] exclude_private: true nav_item_prefix: "" module_options: From 679be808cba2f82c864c202d85313175f8bad9c4 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 26 Jun 2025 17:04:40 -0700 Subject: [PATCH 03/25] update features of site --- python/mkdocs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/mkdocs.yml b/python/mkdocs.yml index ef31c78a3..ab4b688b8 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -2,10 +2,12 @@ site_name: Sift Python Client Library repo_url: https://github.com/sift-stack/sift/tree/main/python theme: name: material + features: + - navigation.tabs + - navigation.sections nav: - Home: index.md - - API: sync_apis.md plugins: - search From c9d52c1e3060b4daa2ba8f5ef3f2ebad3a22ccb6 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 26 Jun 2025 17:26:58 -0700 Subject: [PATCH 04/25] clean up --- python/docs/index.md | 11 ----------- python/mkdocs.yml | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/python/docs/index.md b/python/docs/index.md index 290487123..000ea3455 100644 --- a/python/docs/index.md +++ b/python/docs/index.md @@ -15,14 +15,3 @@ For full documentation visit [mkdocs.org](https://www.mkdocs.org). docs/ index.md # The documentation homepage. ... # Other markdown pages, images and other files. - -# Reference - -## Client - -::: sift_client.client.SiftClient - -## Sync APIs - -::: sift_client.resources.AssetsAPI -::: sift_client.resources.PingAPI \ No newline at end of file diff --git a/python/mkdocs.yml b/python/mkdocs.yml index ab4b688b8..1c98bb259 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -1,10 +1,30 @@ site_name: Sift Python Client Library repo_url: https://github.com/sift-stack/sift/tree/main/python +copyright: "Copyright 2025 Sift Stack, Inc." theme: name: material + palette: + # Palette toggle for light mode + - scheme: default + primary: grey + accent: deep orange + toggle: + icon: material/brightness-7 + name: Switch to dark mode + # Palette toggle for dark mode + - scheme: slate + primary: black + accent: deep orange + toggle: + icon: material/brightness-4 + name: Switch to light mode + logo: https://avatars.githubusercontent.com/u/105525178?s=200&v=4 features: - navigation.tabs - navigation.sections + - toc.follow + - navigation.top + - search.suggest nav: - Home: index.md @@ -23,7 +43,7 @@ plugins: find_stubs_package: true show_if_no_docstring: true # TODO: custom griffe plugin instead - # force_inspection: true # Needed for run-time generated sync_stubs + force_inspection: true # Needed for run-time generated sync_stubs # filters: [ "!^__", "!^_abc_", "!^_", "!TYPE_CHECKING" ] filters: "public" show_submodules: false From d02afe4477d136ad626b417652de714b5be1dd84 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 26 Jun 2025 18:38:43 -0700 Subject: [PATCH 05/25] add custom griffe extension for inspection of the Sync implementations --- python/griffe_extensions/__init__.py | 3 +++ .../griffe_extensions/sync_stubs_inspector.py | 21 ++++++++++++++++++ python/mkdocs.yml | 22 +++++-------------- 3 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 python/griffe_extensions/__init__.py create mode 100644 python/griffe_extensions/sync_stubs_inspector.py diff --git a/python/griffe_extensions/__init__.py b/python/griffe_extensions/__init__.py new file mode 100644 index 000000000..8a5014afa --- /dev/null +++ b/python/griffe_extensions/__init__.py @@ -0,0 +1,3 @@ +from griffe_extensions.sync_stubs_inspector import InspectSpecificObjects + +__all__ = ["InspectSpecificObjects"] diff --git a/python/griffe_extensions/sync_stubs_inspector.py b/python/griffe_extensions/sync_stubs_inspector.py new file mode 100644 index 000000000..ec83e2600 --- /dev/null +++ b/python/griffe_extensions/sync_stubs_inspector.py @@ -0,0 +1,21 @@ +import griffe + +logger = griffe.get_logger("griffe_inspect_specific_objects") + + +class InspectSpecificObjects(griffe.Extension): + """Only inspect specific objects (such as ones with stubs)""" + + def __init__(self, paths: list[str]) -> None: + self.objects = paths + + def on_instance(self, *, obj: griffe.Object, **kwargs) -> None: + if obj.path not in self.objects: + return + + # Skip over the stub files themselves + if str(obj.filepath).endswith(".pyi"): + return + # Load the stub file instead of importing the .py + inspected_module = griffe.inspect(obj.module.path, filepath=obj.filepath) + obj.parent.set_member(obj.name, inspected_module[obj.name]) diff --git a/python/mkdocs.yml b/python/mkdocs.yml index 1c98bb259..c5f2e65de 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -39,16 +39,10 @@ plugins: options: load_external_modules: true show_source: false - allow_inspection: true find_stubs_package: true show_if_no_docstring: true - # TODO: custom griffe plugin instead - force_inspection: true # Needed for run-time generated sync_stubs - # filters: [ "!^__", "!^_abc_", "!^_", "!TYPE_CHECKING" ] filters: "public" show_submodules: false - # Explicitly include stubs directory - search_path: [ "../lib" ] # Styling group_by_category: true docstring_section_style: spacy @@ -62,18 +56,14 @@ plugins: show_symbol_type_heading: true show_symbol_type_toc: true summary: true - # Disabled until custom griffe plugin otherwise fails due to force_inspection - # extensions: - # - griffe_pydantic: - # schema: true + # Custom Griffe extension to only inspect sync_stubs + extensions: + - griffe_extensions/sync_stubs_inspector.py:InspectSpecificObjects: + paths: + - sift_client.resources.sync_stubs + - api-autonav: modules: [ lib/sift_client ] #, lib/sift ] exclude_private: true nav_item_prefix: "" - module_options: - # special filters to avoid rendering the async again - sift_client.resources.sync_stubs: - filters: [ "!Async$", "!^__", "!^_abc_", "!^generate" ] - - From 78b179cf338a706c57a94ee609eea8f9ce8d41c9 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 26 Jun 2025 18:43:15 -0700 Subject: [PATCH 06/25] add custom griffe extension for inspection of the Sync implementations --- python/lib/sift_client/util/cel_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/lib/sift_client/util/cel_utils.py b/python/lib/sift_client/util/cel_utils.py index d6e0a38b5..53767978b 100644 --- a/python/lib/sift_client/util/cel_utils.py +++ b/python/lib/sift_client/util/cel_utils.py @@ -215,6 +215,7 @@ def greater_than(field: str, value: int | float | datetime) -> str: return f"{field} > {as_string}" + def less_than(field: str, value: int | float | datetime) -> str: """ Generates a CEL expression that checks whether a numeric or datetime field is less than a given value. From ff4a8bc0d3cefd995d5d06be38be0aa0e7eb110a Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 20 Aug 2025 14:00:43 -0700 Subject: [PATCH 07/25] clean up client.py --- python/lib/sift_client/client.py | 33 ++++++++++++----------------- python/lib/sift_client/util/util.py | 26 +++++++++++++++++++++++ python/mkdocs.yml | 5 ++++- python/pyproject.toml | 2 +- 4 files changed, 44 insertions(+), 22 deletions(-) create mode 100644 python/lib/sift_client/util/util.py diff --git a/python/lib/sift_client/client.py b/python/lib/sift_client/client.py index 476c4577b..c3915366d 100644 --- a/python/lib/sift_client/client.py +++ b/python/lib/sift_client/client.py @@ -1,7 +1,5 @@ from __future__ import annotations -from typing import NamedTuple - from sift_client.errors import _sift_client_experimental_warning from sift_client.resources import ( AssetsAPI, @@ -22,23 +20,11 @@ WithGrpcClient, WithRestClient, ) +from sift_client.util.util import AsyncAPIs _sift_client_experimental_warning() -class AsyncAPIs(NamedTuple): - """Simple accessor for the asynchronous APIs, still uses the SiftClient instance.""" - - """Instance of the Ping API for making asynchronous requests.""" - ping: PingAPIAsync - """Instance of the Assets API for making asynchronous requests.""" - assets: AssetsAPIAsync - """Instance of the Calculated Channels API for making asynchronous requests.""" - calculated_channels: CalculatedChannelsAPIAsync - """Instance of the Runs API for making asynchronous requests.""" - runs: RunsAPIAsync - - class SiftClient( WithGrpcClient, WithRestClient, @@ -48,7 +34,7 @@ class SiftClient( It provides both synchronous and asynchronous interfaces, strong type checking, and a Pythonic API design. - Example usage: + Examples: from sift_client import SiftClient from datetime import datetime @@ -72,14 +58,21 @@ class SiftClient( response = await sift.async_.ping.ping() """ - """Instance of the Ping API for making synchronous requests.""" + ping: PingAPI - """Instance of the Assets API for making synchronous requests.""" + """Instance of the Ping API for making synchronous requests.""" + assets: AssetsAPI - """Instance of the Calculated Channels API for making synchronous requests.""" + """Instance of the Assets API for making synchronous requests.""" + calculated_channels: CalculatedChannelsAPI - """Instance of the Runs API for making synchronous requests.""" + """Instance of the Calculated Channels API for making synchronous requests.""" + runs: RunsAPI + """Instance of the Runs API for making synchronous requests.""" + + async_: AsyncAPIs + """Accessor for the asynchronous APIs. All asynchronous APIs are available as attributes on this accessor.""" def __init__( self, diff --git a/python/lib/sift_client/util/util.py b/python/lib/sift_client/util/util.py new file mode 100644 index 000000000..d9f74ab5a --- /dev/null +++ b/python/lib/sift_client/util/util.py @@ -0,0 +1,26 @@ +from __future__ import annotations + +from typing import NamedTuple + +from sift_client.resources import ( + AssetsAPIAsync, + CalculatedChannelsAPIAsync, + PingAPIAsync, + RunsAPIAsync, +) + + +class AsyncAPIs(NamedTuple): + """Simple accessor for the asynchronous APIs, still uses the SiftClient instance.""" + + ping: PingAPIAsync + """Instance of the Ping API for making asynchronous requests.""" + + assets: AssetsAPIAsync + """Instance of the Assets API for making asynchronous requests.""" + + calculated_channels: CalculatedChannelsAPIAsync + """Instance of the Calculated Channels API for making asynchronous requests.""" + + runs: RunsAPIAsync + """Instance of the Runs API for making asynchronous requests.""" diff --git a/python/mkdocs.yml b/python/mkdocs.yml index c5f2e65de..188cb119c 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -36,7 +36,10 @@ plugins: default_handler: python handlers: python: + import: + - https://docs.python.org/3/objects.inv options: + show_docstring_examples: false load_external_modules: true show_source: false find_stubs_package: true @@ -56,7 +59,7 @@ plugins: show_symbol_type_heading: true show_symbol_type_toc: true summary: true - # Custom Griffe extension to only inspect sync_stubs + # Custom Griffe extension to inspect the sync stubs and generate their signatures extensions: - griffe_extensions/sync_stubs_inspector.py:InspectSpecificObjects: paths: diff --git a/python/pyproject.toml b/python/pyproject.toml index 9ac9a8292..397f1b510 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -55,7 +55,7 @@ development = [ "ruff", ] build = ["pdoc==14.5.0", "build==1.2.1"] -docs = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mkdocs-include-markdown-plugin"] +docs = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mkdocs-include-markdown-plugin", "mkdocs-api-autonav"] openssl = ["pyOpenSSL<24.0.0", "types-pyOpenSSL<24.0.0", "cffi~=1.14"] tdms = ["npTDMS~=1.9"] rosbags = ["rosbags~=0.0"] From 9a7909d0a5f9c38f73384a4b324053114a1907b4 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 20 Aug 2025 14:24:03 -0700 Subject: [PATCH 08/25] add mike for versioning of the docs --- python/mkdocs.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/mkdocs.yml b/python/mkdocs.yml index 188cb119c..ef152ce2f 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -26,12 +26,19 @@ theme: - navigation.top - search.suggest +extra: + version: + provider: mike + alias: true + nav: - Home: index.md plugins: - search - autorefs + - mike: # For docs versioning + deploy_prefix: 'python' # In case we want to use doc sites for other client libs too - mkdocstrings: default_handler: python handlers: From 64f332b4ad865200d3bb4b8ab5f43a4a0b2f9950 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 20 Aug 2025 14:52:05 -0700 Subject: [PATCH 09/25] add mike auto building and deploy --- .github/workflows/python_build_docs.yml | 109 ++++++++++++++++++++++++ .github/workflows/python_release.yaml | 43 +++++++++- python/pyproject.toml | 2 +- 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/python_build_docs.yml diff --git a/.github/workflows/python_build_docs.yml b/.github/workflows/python_build_docs.yml new file mode 100644 index 000000000..f1fcfdb42 --- /dev/null +++ b/.github/workflows/python_build_docs.yml @@ -0,0 +1,109 @@ +name: Build and Deploy Python Docs (Dev) + +on: + pull_request: + types: [opened, synchronize, closed] + paths: + - 'python/docs/**' + - 'python/lib/**' + - 'python/mkdocs.yml' + - 'python/pyproject.toml' + workflow_dispatch: + inputs: + deploy_to_dev: + description: 'Deploy to dev alias using commit hash as version' + required: false + default: true + type: boolean + +jobs: + build_docs: + if: github.event.action != 'closed' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch full history for mike + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + cd python + pip install -e .[docs] + + - name: Extract version + id: version + run: | + # Use commit hash as version for dev deployments + VERSION=$(git rev-parse --short HEAD) + + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + # Use PR number as alias for PR deployments + ALIAS="pr-${{ github.event.number }}" + else + # Use 'dev' for manual workflow dispatch + ALIAS="dev" + fi + + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "alias=$ALIAS" >> $GITHUB_OUTPUT + echo "Dev deployment - Version: $VERSION, Alias: $ALIAS" + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Deploy docs with mike + run: | + cd python + mike deploy ${{ steps.version.outputs.version }} ${{ steps.version.outputs.alias }} --push --update-aliases + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + cleanup_docs: + if: github.event.action == 'closed' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch full history for mike + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + cd python + pip install -e .[docs] + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Delete PR docs + run: | + cd python + PR_ALIAS="pr-${{ github.event.number }}" + echo "Deleting docs for: $PR_ALIAS" + + # Check if the PR docs exist before trying to delete + if mike list | grep -q "$PR_ALIAS"; then + mike delete "$PR_ALIAS" --push + echo "Successfully deleted docs for $PR_ALIAS" + else + echo "No docs found for $PR_ALIAS, nothing to delete" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/python_release.yaml b/.github/workflows/python_release.yaml index 3c8be0286..f6aaf4948 100644 --- a/.github/workflows/python_release.yaml +++ b/.github/workflows/python_release.yaml @@ -87,4 +87,45 @@ jobs: echo "Uploading archive: $archive" gh release upload "$TAG_NAME" "$archive" --clobber done - + + deploy-docs: + name: Deploy Documentation + needs: publish-to-pypi + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch full history for mike + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + cd python + pip install -e .[docs] + + - name: Extract version from tag + id: version + run: | + # Extract version from tag (everything after 'python/') + VERSION=${GITHUB_REF#refs/tags/python/} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Extracted version: $VERSION" + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Deploy docs with mike + run: | + cd python + mike deploy ${{ steps.version.outputs.version }} latest --push --update-aliases + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/python/pyproject.toml b/python/pyproject.toml index 397f1b510..706ee524e 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -55,7 +55,7 @@ development = [ "ruff", ] build = ["pdoc==14.5.0", "build==1.2.1"] -docs = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mkdocs-include-markdown-plugin", "mkdocs-api-autonav"] +docs = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mkdocs-include-markdown-plugin", "mkdocs-api-autonav", "mike"] openssl = ["pyOpenSSL<24.0.0", "types-pyOpenSSL<24.0.0", "cffi~=1.14"] tdms = ["npTDMS~=1.9"] rosbags = ["rosbags~=0.0"] From f6106683711145ab0f112a50097b071f5d850d23 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 20 Aug 2025 14:57:25 -0700 Subject: [PATCH 10/25] hide pr versions from dropdown --- .github/workflows/python_build_docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python_build_docs.yml b/.github/workflows/python_build_docs.yml index f1fcfdb42..e6af74ba5 100644 --- a/.github/workflows/python_build_docs.yml +++ b/.github/workflows/python_build_docs.yml @@ -62,7 +62,8 @@ jobs: - name: Deploy docs with mike run: | cd python - mike deploy ${{ steps.version.outputs.version }} ${{ steps.version.outputs.alias }} --push --update-aliases + # Deploy dev/PR docs with hidden property to hide from version dropdown + mike deploy ${{ steps.version.outputs.version }} ${{ steps.version.outputs.alias }} --push --update-aliases --prop-set hidden=true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 164e79a8951d92aa8c02ce6a9056f9cedebf73a3 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 20 Aug 2025 15:00:03 -0700 Subject: [PATCH 11/25] hide pr versions from dropdown --- .github/workflows/python_build_docs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python_build_docs.yml b/.github/workflows/python_build_docs.yml index e6af74ba5..ab6940b2b 100644 --- a/.github/workflows/python_build_docs.yml +++ b/.github/workflows/python_build_docs.yml @@ -20,6 +20,8 @@ jobs: build_docs: if: github.event.action != 'closed' runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Checkout code uses: actions/checkout@v4 @@ -63,7 +65,7 @@ jobs: run: | cd python # Deploy dev/PR docs with hidden property to hide from version dropdown - mike deploy ${{ steps.version.outputs.version }} ${{ steps.version.outputs.alias }} --push --update-aliases --prop-set hidden=true + mike deploy ${{ steps.version.outputs.alias }} --push --update-aliases --prop-set hidden=true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9bdfeed2a2f5297d906072134f66fe9515d2ee4e Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 20 Aug 2025 15:44:54 -0700 Subject: [PATCH 12/25] update python release doc logic --- .github/workflows/python_release.yaml | 49 ++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python_release.yaml b/.github/workflows/python_release.yaml index f6aaf4948..278475fa3 100644 --- a/.github/workflows/python_release.yaml +++ b/.github/workflows/python_release.yaml @@ -110,13 +110,42 @@ jobs: cd python pip install -e .[docs] - - name: Extract version from tag + - name: Extract version and check if stable id: version run: | # Extract version from tag (everything after 'python/') - VERSION=${GITHUB_REF#refs/tags/python/} + FULL_VERSION=${GITHUB_REF#refs/tags/python/} + echo "Full version from tag: $FULL_VERSION" + + # Extract major.minor from version (drop patch) + if [[ "$FULL_VERSION" =~ ^v?([0-9]+)\.([0-9]+)\.[0-9]+(.*)?$ ]]; then + MAJOR=${BASH_REMATCH[1]} + MINOR=${BASH_REMATCH[2]} + SUFFIX=${BASH_REMATCH[3]} + VERSION="v${MAJOR}.${MINOR}" + + # Check if this is a stable release (no suffix like -alpha, -beta, -rc) + if [[ -z "$SUFFIX" ]]; then + # Stable release - use 'latest' alias and make visible + ALIAS="latest" + HIDDEN="false" + echo "Stable release detected: $FULL_VERSION -> $VERSION" + else + # Pre-release (alpha, beta, rc) - no 'latest' alias and hide from dropdown + VERSION="${VERSION}${SUFFIX}" + ALIAS="" + HIDDEN="true" + echo "Pre-release detected: $FULL_VERSION -> $VERSION" + fi + else + echo "Error: Could not parse version format: $FULL_VERSION" + exit 1 + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Extracted version: $VERSION" + echo "alias=$ALIAS" >> $GITHUB_OUTPUT + echo "hidden=$HIDDEN" >> $GITHUB_OUTPUT + echo "Final - Version: $VERSION, Alias: $ALIAS, Hidden: $HIDDEN" - name: Configure Git run: | @@ -126,6 +155,18 @@ jobs: - name: Deploy docs with mike run: | cd python - mike deploy ${{ steps.version.outputs.version }} latest --push --update-aliases + VERSION="${{ steps.version.outputs.version }}" + ALIAS="${{ steps.version.outputs.alias }}" + HIDDEN="${{ steps.version.outputs.hidden }}" + + # Always deploy the full version first, but hide it + echo "Deploying full version $FULL_VERSION (hidden)" + mike deploy "$FULL_VERSION" --push --prop-set hidden=true + + if [[ "$HIDDEN" == "false" ]]; then + # Stable release: deploy abbreviated version with latest alias, visible in dropdown + echo "Deploying stable release $VERSION with $ALIAS alias" + mike deploy "$VERSION" "$ALIAS" --push --update-aliases + fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d6bd928a0e1f47e11d5eba460ce02ff6676942dd Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 21 Aug 2025 10:09:38 -0700 Subject: [PATCH 13/25] clean up docs --- python/docs/index.md | 75 ++++++- python/docs/overrides/main.html | 10 + python/lib/sift_client/__init__.py | 207 ++++++++++++++++++ .../sift_client/{tests => _tests}/__init__.py | 0 .../{tests => _tests}/_internal/__init__.py | 0 .../_internal/test_gen_pyi.py | 0 .../_internal/test_stub_module/__init__.py | 2 +- .../_internal/test_stub_module/test_py.py | 0 .../_internal/test_sync_wrapper.py | 0 .../integrated/calculated_channels.py | 0 .../{tests => _tests}/integrated/channels.py | 0 .../{tests => _tests}/integrated/runs.py | 0 .../{tests => _tests}/util/__init__.py | 0 .../{tests => _tests}/util/test_cel_utils.py | 0 python/lib/sift_client/client.py | 3 + python/mkdocs.yml | 22 +- 16 files changed, 305 insertions(+), 14 deletions(-) create mode 100644 python/docs/overrides/main.html rename python/lib/sift_client/{tests => _tests}/__init__.py (100%) rename python/lib/sift_client/{tests => _tests}/_internal/__init__.py (100%) rename python/lib/sift_client/{tests => _tests}/_internal/test_gen_pyi.py (100%) rename python/lib/sift_client/{tests => _tests}/_internal/test_stub_module/__init__.py (67%) rename python/lib/sift_client/{tests => _tests}/_internal/test_stub_module/test_py.py (100%) rename python/lib/sift_client/{tests => _tests}/_internal/test_sync_wrapper.py (100%) rename python/lib/sift_client/{tests => _tests}/integrated/calculated_channels.py (100%) rename python/lib/sift_client/{tests => _tests}/integrated/channels.py (100%) rename python/lib/sift_client/{tests => _tests}/integrated/runs.py (100%) rename python/lib/sift_client/{tests => _tests}/util/__init__.py (100%) rename python/lib/sift_client/{tests => _tests}/util/test_cel_utils.py (100%) diff --git a/python/docs/index.md b/python/docs/index.md index 000ea3455..40e38f2db 100644 --- a/python/docs/index.md +++ b/python/docs/index.md @@ -1,17 +1,68 @@ -# Welcome to MkDocs +# Sift Python Client Library +Welcome to the official Python client library for Sift! This library provides a high-level Python API on top of Sift's protocol buffers, designed to ergonomically interface with the Sift gRPC API and simplify the process of streaming data. -For full documentation visit [mkdocs.org](https://www.mkdocs.org). +Sift provides official client libraries for select languages, designed to simplify the process of streaming data over gRPC. These client libraries utilize ingestion-config-based streaming to facilitate data transmission. -## Commands +Check out the [repository](https://github.com/sift-stack/sift) for a list of all available client libraries. -* `mkdocs new [dir-name]` - Create a new project. -* `mkdocs serve` - Start the live-reloading docs server. -* `mkdocs build` - Build the documentation site. -* `mkdocs -h` - Print help message and exit. +## Installation -## Project layout +To install the Sift Python library: - mkdocs.yml # The configuration file. - docs/ - index.md # The documentation homepage. - ... # Other markdown pages, images and other files. +```bash +pip install sift-stack-py +``` + +## API Documentation + +This documentation covers two Python APIs for interacting with Sift: + +### Sift Py API (Legacy) + +The original low-level Python API that provides direct access to Sift's protocol buffer interfaces. + +Browse the [**Sift Py API**][sift_py] section for complete reference documentation. + +**Use this API if you need:** + +- Direct protocol buffer access +- Fine-grained control over gRPC connections +- Legacy compatibility with existing code + +### Sift Client API (New) + +!!! warning + The Sift Client is experimental and is subject to change. + + +The modern, high-level client library that provides all the ergonomic features missing from the original API. This new client offers intuitive Python interfaces, strong type safety, automatic connection management, and both synchronous and asynchronous support. + +Explore the [**Sift Client API (New)**][sift_client] section for the complete API reference. + +**Key improvements over Sift Py:** + +- **Ergonomic Design** - Pythonic interfaces instead of raw protocol buffers +- **Type Safety** - Full type hints and Pydantic model validation +- **Dual APIs** - Both sync and async support for all operations +- **Auto Connection Management** - No manual gRPC connection handling +- **Rich Object Models** - Immutable types with convenient methods +- **Modern Patterns** - Context managers, iterators, and Python best practices + + +## Getting Help + +- **API Reference** - Browse the complete API documentation in the navigation +- **Examples** - Check out code examples throughout the documentation +- **GitHub** - Visit our [repository](https://github.com/sift-stack/sift) for issues and contributions + +## What's Next? + +Ready to dive deeper? Explore the API documentation to learn about: + +- **Sift Resources** - Creating, updating, and organizing your assets and other data +- **Data Streaming** - Efficient methods for ingesting data +- **Advanced Filtering** - Powerful query capabilities +- **Error Handling** - Best practices for robust applications +- **Performance Optimization** - Tips for high-throughput scenarios + +Get started by exploring the API reference in the navigation menu! diff --git a/python/docs/overrides/main.html b/python/docs/overrides/main.html new file mode 100644 index 000000000..648b7a6fe --- /dev/null +++ b/python/docs/overrides/main.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} + +{% block outdated %} +You're not viewing the latest version. + + + + Click here to go to latest. + +{% endblock %} diff --git a/python/lib/sift_client/__init__.py b/python/lib/sift_client/__init__.py index 928b6dc31..a9da51663 100644 --- a/python/lib/sift_client/__init__.py +++ b/python/lib/sift_client/__init__.py @@ -1,2 +1,209 @@ + +""" +!!! warning + The Sift Client is experimental and is subject to change. + + +# Sift Client Library + +This library provides a high-level Python client for interacting with Sift APIs. It offers both synchronous and +asynchronous interfaces, strong type checking, and a Pythonic API design. + +## Installation + +```bash +pip install sift-stack-py +``` + +## Getting Started + +### Initializing the Client + +You can initialize the Sift client with your API key and service URLs: + +```python +from sift_client import SiftClient +from datetime import datetime + +# Initialize with individual parameters +client = SiftClient( + api_key="your-api-key", + grpc_url="your-sift-grpc-url", + rest_url="your-sift-rest-url" +) + +# Or use a connection configuration +from sift_client.transport import SiftConnectionConfig + +config = SiftConnectionConfig( + api_key="your-api-key", + grpc_url="your-sift-grpc-url", + rest_url="your-sift-rest-url" +) +client = SiftClient(connection_config=config) +``` + +The `SiftConnectionConfig` provides access to additional configuration options such as `use_ssl` and `cert_via_openssl`. + +### Using Synchronous and Asynchronous APIs + +The Sift client provides both synchronous and asynchronous versions of all APIs. You can choose the one that best fits +your application's needs. + +#### Synchronous API + +The synchronous API is perfect for scripts, notebooks, and applications that don't need asynchronous operation: + +```python +# Get an asset by ID +asset = client.assets.get(asset_id="asset123") + +# List assets with filtering +assets = client.assets.list_( + name_contains="example", + created_after=datetime(2023, 1, 1), + include_archived=False +) + +# Find a single asset matching criteria +asset = client.assets.find(name="my-asset") +``` + +#### Asynchronous API + +The asynchronous API is ideal for high-performance applications and services that need to make concurrent API calls: + +```python +import asyncio + + +async def get_asset_async(): + # Get an asset by ID asynchronously + asset = await client.assets_async.get(asset_id="asset123") + + # Running Sync within async also works + some_other_asset = client.assets.get(asset_id="asset456") + + return asset + + +# Run in an async context +asset = asyncio.run(get_asset_async()) + +``` + +### Working with Sift Types + +Sift types (like `Asset`, `Run`, etc.) are immutable Pydantic models that provide a convenient interface for working +with Sift resources. + +#### Accessing Properties + +```python +# Get an asset +asset = client.assets.get(asset_id="asset123") + +# Access properties +print(f"Asset name: {asset.name}") +print(f"Created on: {asset.created_date}") +print(f"Tags: {', '.join(asset.tags)}") +print(f"Is archived: {asset.is_archived}") +``` + +#### Using Methods on Sift Types + +Sift types have convenient methods for common operations. These methods use the synchronous API internally. +**Using these methods will update the instance in-place.** + +```python +# Get an asset +asset = client.assets.get(asset_id="asset123") + +# Archive the asset +asset.archive(archive_runs=True) + +# Update the asset +asset.update({ + "tags": ["updated", "example"] +}) +``` + +> **Note:** Type methods only work with the synchronous API. If you need to use the asynchronous API, you should use the +> resource APIs directly. + +#### Creating Update Models + +For more complex updates, you can create update models (instead of a key-value dictionary): + +```python +from sift_client.types.asset import AssetUpdate + +# Create an update model +update = AssetUpdate(tags=["new", "tags"]) + +# Apply the update +asset = client.assets.update(asset="asset123", update=update) + +# Or using the asset method +asset = client.assets.get(asset_id="asset123").update(update) +``` + +## Advanced Usage + +### Working with Tags + +Tags are a powerful way to organize and filter your assets: + +```python +# Add tags when updating an asset +asset.update({ + "tags": ["production", "model-v1", "trained"] +}) + +# Filter assets by tags +production_assets = client.assets.list_( + tags=["production"] +) +``` + +### Filtering Assets + +The client provides various ways to filter different Sift types: + +```python +# Filter by name (exact match) +assets = client.assets.list_(name="my-model") + +# Filter by name (contains) +assets = client.assets.list_(name_contains="model") + +# Filter by name (regex) +assets = client.assets.list_(name_regex="model-v[0-9]+") + +# Filter by creation date +assets = client.assets.list_( + created_after=datetime(2023, 1, 1), + created_before=datetime(2023, 12, 31) +) + +# Filter by modification date +assets = client.assets.list_( + modified_after=datetime(2023, 6, 1) +) + +# Include archived assets +all_assets = client.assets.list_(include_archived=True) + +# Limit the number of results +recent_assets = client.assets.list_( + limit=10, + order_by="modified_date desc" +) +``` + + +""" + + from sift_client.client import SiftClient from sift_client.transport import SiftConnectionConfig diff --git a/python/lib/sift_client/tests/__init__.py b/python/lib/sift_client/_tests/__init__.py similarity index 100% rename from python/lib/sift_client/tests/__init__.py rename to python/lib/sift_client/_tests/__init__.py diff --git a/python/lib/sift_client/tests/_internal/__init__.py b/python/lib/sift_client/_tests/_internal/__init__.py similarity index 100% rename from python/lib/sift_client/tests/_internal/__init__.py rename to python/lib/sift_client/_tests/_internal/__init__.py diff --git a/python/lib/sift_client/tests/_internal/test_gen_pyi.py b/python/lib/sift_client/_tests/_internal/test_gen_pyi.py similarity index 100% rename from python/lib/sift_client/tests/_internal/test_gen_pyi.py rename to python/lib/sift_client/_tests/_internal/test_gen_pyi.py diff --git a/python/lib/sift_client/tests/_internal/test_stub_module/__init__.py b/python/lib/sift_client/_tests/_internal/test_stub_module/__init__.py similarity index 67% rename from python/lib/sift_client/tests/_internal/test_stub_module/__init__.py rename to python/lib/sift_client/_tests/_internal/test_stub_module/__init__.py index 9fd1ebcaf..3352b01d6 100644 --- a/python/lib/sift_client/tests/_internal/test_stub_module/__init__.py +++ b/python/lib/sift_client/_tests/_internal/test_stub_module/__init__.py @@ -1,6 +1,6 @@ from __future__ import annotations from sift_client._internal.sync_wrapper import generate_sync_api -from sift_client.tests._internal.test_stub_module.test_py import MockClassAsync +from sift_client._tests._internal.test_stub_module.test_py import MockClassAsync MockClass: type = generate_sync_api(MockClassAsync, "MockClass") diff --git a/python/lib/sift_client/tests/_internal/test_stub_module/test_py.py b/python/lib/sift_client/_tests/_internal/test_stub_module/test_py.py similarity index 100% rename from python/lib/sift_client/tests/_internal/test_stub_module/test_py.py rename to python/lib/sift_client/_tests/_internal/test_stub_module/test_py.py diff --git a/python/lib/sift_client/tests/_internal/test_sync_wrapper.py b/python/lib/sift_client/_tests/_internal/test_sync_wrapper.py similarity index 100% rename from python/lib/sift_client/tests/_internal/test_sync_wrapper.py rename to python/lib/sift_client/_tests/_internal/test_sync_wrapper.py diff --git a/python/lib/sift_client/tests/integrated/calculated_channels.py b/python/lib/sift_client/_tests/integrated/calculated_channels.py similarity index 100% rename from python/lib/sift_client/tests/integrated/calculated_channels.py rename to python/lib/sift_client/_tests/integrated/calculated_channels.py diff --git a/python/lib/sift_client/tests/integrated/channels.py b/python/lib/sift_client/_tests/integrated/channels.py similarity index 100% rename from python/lib/sift_client/tests/integrated/channels.py rename to python/lib/sift_client/_tests/integrated/channels.py diff --git a/python/lib/sift_client/tests/integrated/runs.py b/python/lib/sift_client/_tests/integrated/runs.py similarity index 100% rename from python/lib/sift_client/tests/integrated/runs.py rename to python/lib/sift_client/_tests/integrated/runs.py diff --git a/python/lib/sift_client/tests/util/__init__.py b/python/lib/sift_client/_tests/util/__init__.py similarity index 100% rename from python/lib/sift_client/tests/util/__init__.py rename to python/lib/sift_client/_tests/util/__init__.py diff --git a/python/lib/sift_client/tests/util/test_cel_utils.py b/python/lib/sift_client/_tests/util/test_cel_utils.py similarity index 100% rename from python/lib/sift_client/tests/util/test_cel_utils.py rename to python/lib/sift_client/_tests/util/test_cel_utils.py diff --git a/python/lib/sift_client/client.py b/python/lib/sift_client/client.py index c3915366d..cc30cb662 100644 --- a/python/lib/sift_client/client.py +++ b/python/lib/sift_client/client.py @@ -34,6 +34,9 @@ class SiftClient( It provides both synchronous and asynchronous interfaces, strong type checking, and a Pythonic API design. + !!! warning + The Sift Client is experimental and is subject to change. + Examples: from sift_client import SiftClient from datetime import datetime diff --git a/python/mkdocs.yml b/python/mkdocs.yml index ef152ce2f..179871de0 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -1,8 +1,10 @@ site_name: Sift Python Client Library +site_url: https://sift-stack.github.io/sift/python/ repo_url: https://github.com/sift-stack/sift/tree/main/python copyright: "Copyright 2025 Sift Stack, Inc." theme: name: material + custom_dir: docs/overrides palette: # Palette toggle for light mode - scheme: default @@ -72,8 +74,26 @@ plugins: paths: - sift_client.resources.sync_stubs + - api-autonav: + nav_section_title: Sift Py API + modules: [ lib/sift_py ] + exclude_private: true + nav_item_prefix: "" - api-autonav: - modules: [ lib/sift_client ] #, lib/sift ] + nav_section_title: Sift Client API (New) + modules: [ lib/sift_client ] exclude_private: true nav_item_prefix: "" + + +markdown_extensions: + - admonition + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences From a378059060ad75ac793a5587aeca2836cd5d254c Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 21 Aug 2025 10:13:52 -0700 Subject: [PATCH 14/25] linting --- python/lib/sift_client/__init__.py | 7 +++++-- python/lib/sift_client/client.py | 1 - python/lib/sift_client/resources/sync_stubs/__init__.py | 7 +------ python/lib/sift_client/util/cel_utils.py | 1 - python/lib/sift_py/asset/_internal/shared.py | 1 + python/lib/sift_py/report/_report_test.py | 1 + python/lib/sift_py/report/service.py | 1 + python/lib/sift_py/rule_evaluation/_service_test.py | 1 + python/lib/sift_py/rule_evaluation/service.py | 1 + 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/python/lib/sift_client/__init__.py b/python/lib/sift_client/__init__.py index a9da51663..edbe5eaba 100644 --- a/python/lib/sift_client/__init__.py +++ b/python/lib/sift_client/__init__.py @@ -1,4 +1,3 @@ - """ !!! warning The Sift Client is experimental and is subject to change. @@ -204,6 +203,10 @@ async def get_asset_async(): """ - from sift_client.client import SiftClient from sift_client.transport import SiftConnectionConfig + +__all__ = [ + "SiftClient", + "SiftConnectionConfig", +] diff --git a/python/lib/sift_client/client.py b/python/lib/sift_client/client.py index cc30cb662..c5623a5c9 100644 --- a/python/lib/sift_client/client.py +++ b/python/lib/sift_client/client.py @@ -61,7 +61,6 @@ class SiftClient( response = await sift.async_.ping.ping() """ - ping: PingAPI """Instance of the Ping API for making synchronous requests.""" diff --git a/python/lib/sift_client/resources/sync_stubs/__init__.py b/python/lib/sift_client/resources/sync_stubs/__init__.py index 947966772..a33bb267c 100644 --- a/python/lib/sift_client/resources/sync_stubs/__init__.py +++ b/python/lib/sift_client/resources/sync_stubs/__init__.py @@ -16,9 +16,4 @@ CalculatedChannelsAPI = generate_sync_api(CalculatedChannelsAPIAsync, "CalculatedChannelsAPI") RunsAPI = generate_sync_api(RunsAPIAsync, "RunsAPI") -__all__ = [ - "PingAPI", - "AssetsAPI", - "CalculatedChannelsAPI", - "RunsAPI" -] +__all__ = ["PingAPI", "AssetsAPI", "CalculatedChannelsAPI", "RunsAPI"] diff --git a/python/lib/sift_client/util/cel_utils.py b/python/lib/sift_client/util/cel_utils.py index 53767978b..d6e0a38b5 100644 --- a/python/lib/sift_client/util/cel_utils.py +++ b/python/lib/sift_client/util/cel_utils.py @@ -215,7 +215,6 @@ def greater_than(field: str, value: int | float | datetime) -> str: return f"{field} > {as_string}" - def less_than(field: str, value: int | float | datetime) -> str: """ Generates a CEL expression that checks whether a numeric or datetime field is less than a given value. diff --git a/python/lib/sift_py/asset/_internal/shared.py b/python/lib/sift_py/asset/_internal/shared.py index 7e503616a..e33a5410c 100644 --- a/python/lib/sift_py/asset/_internal/shared.py +++ b/python/lib/sift_py/asset/_internal/shared.py @@ -2,6 +2,7 @@ from sift.assets.v1.assets_pb2 import Asset, ListAssetsRequest, ListAssetsResponse from sift.assets.v1.assets_pb2_grpc import AssetServiceStub + from sift_py._internal.cel import cel_in diff --git a/python/lib/sift_py/report/_report_test.py b/python/lib/sift_py/report/_report_test.py index a50344dee..8d13f76e5 100644 --- a/python/lib/sift_py/report/_report_test.py +++ b/python/lib/sift_py/report/_report_test.py @@ -7,6 +7,7 @@ ReportRuleStatus, ReportRuleSummary, ) + from sift_py._internal.test_util.channel import MockChannel from sift_py.report.service import ReportService diff --git a/python/lib/sift_py/report/service.py b/python/lib/sift_py/report/service.py index 26c2595eb..5c1f8a9ac 100644 --- a/python/lib/sift_py/report/service.py +++ b/python/lib/sift_py/report/service.py @@ -4,6 +4,7 @@ from sift.reports.v1.reports_pb2 import GetReportRequest, GetReportResponse, ReportRuleStatus from sift.reports.v1.reports_pb2 import Report as Report_pb2 from sift.reports.v1.reports_pb2_grpc import ReportServiceStub + from sift_py.grpc.transport import SiftChannel NOT_RUNNING_STATUS = [ diff --git a/python/lib/sift_py/rule_evaluation/_service_test.py b/python/lib/sift_py/rule_evaluation/_service_test.py index 51e40c7eb..b95e0e3b5 100644 --- a/python/lib/sift_py/rule_evaluation/_service_test.py +++ b/python/lib/sift_py/rule_evaluation/_service_test.py @@ -6,6 +6,7 @@ EvaluateRulesResponse, ) from sift.rules.v1.rules_pb2 import BatchUpdateRulesResponse + from sift_py._internal.test_util.channel import MockChannel from sift_py.report_templates.config import ReportTemplateConfig from sift_py.rule.config import ( diff --git a/python/lib/sift_py/rule_evaluation/service.py b/python/lib/sift_py/rule_evaluation/service.py index d53431687..c04f3f9c3 100644 --- a/python/lib/sift_py/rule_evaluation/service.py +++ b/python/lib/sift_py/rule_evaluation/service.py @@ -23,6 +23,7 @@ RunTimeRange, ) from sift.rule_evaluation.v1.rule_evaluation_pb2_grpc import RuleEvaluationServiceStub + from sift_py._internal.time import to_timestamp_pb from sift_py.grpc.transport import SiftChannel from sift_py.report.service import ReportService From ada8fba0084a9483d99abe0bd34136ebe7e5cfdd Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 21 Aug 2025 12:03:40 -0700 Subject: [PATCH 15/25] pin ruff version --- python/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index 706ee524e..fe5735604 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -52,7 +52,7 @@ development = [ "pytest-asyncio==0.23.7", "pytest-benchmark==4.0.0", "pytest-mock==3.14.0", - "ruff", + "ruff~=0.12.10", ] build = ["pdoc==14.5.0", "build==1.2.1"] docs = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mkdocs-include-markdown-plugin", "mkdocs-api-autonav", "mike"] From 00a3ca539e2131d265981f33ef1df8dee4c30110 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Thu, 21 Aug 2025 12:10:14 -0700 Subject: [PATCH 16/25] fix linting --- python/lib/sift_py/asset/_internal/shared.py | 1 - python/lib/sift_py/report/_report_test.py | 1 - python/lib/sift_py/report/service.py | 1 - python/lib/sift_py/rule_evaluation/_service_test.py | 1 - python/lib/sift_py/rule_evaluation/service.py | 1 - 5 files changed, 5 deletions(-) diff --git a/python/lib/sift_py/asset/_internal/shared.py b/python/lib/sift_py/asset/_internal/shared.py index e33a5410c..7e503616a 100644 --- a/python/lib/sift_py/asset/_internal/shared.py +++ b/python/lib/sift_py/asset/_internal/shared.py @@ -2,7 +2,6 @@ from sift.assets.v1.assets_pb2 import Asset, ListAssetsRequest, ListAssetsResponse from sift.assets.v1.assets_pb2_grpc import AssetServiceStub - from sift_py._internal.cel import cel_in diff --git a/python/lib/sift_py/report/_report_test.py b/python/lib/sift_py/report/_report_test.py index 8d13f76e5..a50344dee 100644 --- a/python/lib/sift_py/report/_report_test.py +++ b/python/lib/sift_py/report/_report_test.py @@ -7,7 +7,6 @@ ReportRuleStatus, ReportRuleSummary, ) - from sift_py._internal.test_util.channel import MockChannel from sift_py.report.service import ReportService diff --git a/python/lib/sift_py/report/service.py b/python/lib/sift_py/report/service.py index 5c1f8a9ac..26c2595eb 100644 --- a/python/lib/sift_py/report/service.py +++ b/python/lib/sift_py/report/service.py @@ -4,7 +4,6 @@ from sift.reports.v1.reports_pb2 import GetReportRequest, GetReportResponse, ReportRuleStatus from sift.reports.v1.reports_pb2 import Report as Report_pb2 from sift.reports.v1.reports_pb2_grpc import ReportServiceStub - from sift_py.grpc.transport import SiftChannel NOT_RUNNING_STATUS = [ diff --git a/python/lib/sift_py/rule_evaluation/_service_test.py b/python/lib/sift_py/rule_evaluation/_service_test.py index b95e0e3b5..51e40c7eb 100644 --- a/python/lib/sift_py/rule_evaluation/_service_test.py +++ b/python/lib/sift_py/rule_evaluation/_service_test.py @@ -6,7 +6,6 @@ EvaluateRulesResponse, ) from sift.rules.v1.rules_pb2 import BatchUpdateRulesResponse - from sift_py._internal.test_util.channel import MockChannel from sift_py.report_templates.config import ReportTemplateConfig from sift_py.rule.config import ( diff --git a/python/lib/sift_py/rule_evaluation/service.py b/python/lib/sift_py/rule_evaluation/service.py index c04f3f9c3..d53431687 100644 --- a/python/lib/sift_py/rule_evaluation/service.py +++ b/python/lib/sift_py/rule_evaluation/service.py @@ -23,7 +23,6 @@ RunTimeRange, ) from sift.rule_evaluation.v1.rule_evaluation_pb2_grpc import RuleEvaluationServiceStub - from sift_py._internal.time import to_timestamp_pb from sift_py.grpc.transport import SiftChannel from sift_py.report.service import ReportService From 0b5345a3eada4c8816b9a6bd2562058ee42be2d9 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Mon, 25 Aug 2025 18:14:45 -0700 Subject: [PATCH 17/25] sift styling WIP --- python/docs/stylesheets/extra.css | 202 ++++++++++++++++++++++++++++++ python/mkdocs.yml | 8 ++ 2 files changed, 210 insertions(+) create mode 100644 python/docs/stylesheets/extra.css diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css new file mode 100644 index 000000000..0a2e01bdf --- /dev/null +++ b/python/docs/stylesheets/extra.css @@ -0,0 +1,202 @@ +/* MkDocs Material Dark Theme Overrides - Fumadocs Style */ + +/*.dark {*/ +/* --fd-background: 0 0% 8.04%;*/ +/* --fd-foreground: 0 0% 92%;*/ +/* --fd-muted: 0 0% 12.9%;*/ +/* --fd-muted-foreground: 0 0% 60.9%;*/ +/* --fd-popover: 0 0% 9.8%;*/ +/* --fd-popover-foreground: 0 0% 88%;*/ +/* --fd-card: 0 0% 9.8%;*/ +/* --fd-card-foreground: 0 0% 98%;*/ +/* --fd-border: 0 0% 14%;*/ +/* --fd-primary: 0 0% 98%;*/ +/* --fd-primary-foreground: 0 0% 9%;*/ +/* --fd-secondary: 0 0% 12.9%;*/ +/* --fd-secondary-foreground: 0 0% 98%;*/ +/* --fd-accent: 0 0% 16.9%;*/ +/* --fd-accent-foreground: 0 0% 90%;*/ +/* --fd-ring: 0 0% 14.9%;*/ +/*}*/ + +/*.light {*/ +/* --fd-background: 0 0% 96%;*/ +/* --fd-foreground: 0 0% 3.9%;*/ +/* --fd-muted: 0 0% 96.1%;*/ +/* --fd-muted-foreground: 0 0% 45.1%;*/ +/* --fd-popover: 0 0% 98%;*/ +/* --fd-popover-foreground: 0 0% 15.1%;*/ +/* --fd-card: 0 0% 94.7%;*/ +/* --fd-card-foreground: 0 0% 3.9%;*/ +/* --fd-border: 0 0% 89.8%;*/ +/* --fd-primary: 0 0% 9%;*/ +/* --fd-primary-foreground: 0 0% 98%;*/ +/* --fd-secondary: 0 0% 93.1%;*/ +/* --fd-secondary-foreground: 0 0% 9%;*/ +/* --fd-accent: 0 0% 90.1%;*/ +/* --fd-accent-foreground: 0 0% 9%;*/ +/* --fd-ring: 0 0% 63.9%;*/ +/*}*/ + +/* Brand Colors */ +:root { + --brand-color: #ee4220; +} + +/* Dark theme - define fd variables and map to md variables */ +[data-md-color-scheme="slate"] { + /* Define your color variables */ + /* Map to MkDocs Material variables */ + --md-default-bg-color: rgb(0, 0, 0); + --md-typeset-a-color: var(--brand-color) !important; + --font-foreground-color: rgb(255, 255, 255); + --border-color: rgb(36, 36, 36); + --code-box-background-color: rgb(18, 18, 18); + /*--md-default-fg-color: var(--fd-muted-foreground);*/ + /*--md-typeset-color: var(--fd-muted-foreground);*/ + /*--md-default-fg-color--light: hsl(var(--fd-foreground));*/ + /*--md-default-fg-color--lighter: hsl(var(--fd-foreground) / 0.5);*/ + /*--md-default-fg-color--lightest: hsl(var(--fd-foreground) / 0.07);*/ + /*--md-code-bg-color: hsl(var(--fd-muted));*/ + /*--md-code-fg-color: hsl(var(--fd-foreground));*/ + /*--md-accent-fg-color: hsl(var(--fd-accent-foreground));*/ + /*--md-accent-bg-color: hsl(var(--fd-accent));*/ + /*--md-primary-fg-color: hsl(var(--fd-primary));*/ + /*--md-primary-bg-color: hsl(var(--fd-foreground));*/ + + /* monokai */ + /*--md-code-fg-color: #f8f8f2; !* Default text *!*/ + /*--md-code-bg-color: #272822; !* Background *!*/ + /*--md-code-hl-color: #49483e; !* Highlighted line background *!*/ + + /*--md-code-hl-number-color: #ae81ff; !* Number *!*/ + /*--md-code-hl-special-color: #ff4689; !* Special (tags, deleted, prompt) *!*/ + /*--md-code-hl-function-color: #a6e22e; !* Function, class, decorator, etc. *!*/ + /*--md-code-hl-constant-color: #66d9ef; !* Constants, attributes *!*/ + /*--md-code-hl-keyword-color: #66d9ef; !* Keywords *!*/ + /*--md-code-hl-string-color: #e6db74; !* Strings *!*/ + /*--md-code-hl-name-color: #f8f8f2; !* Generic names *!*/ + /*--md-code-hl-operator-color: #ff4689; !* Operators *!*/ + /*--md-code-hl-punctuation-color: #f8f8f2; !* Punctuation *!*/ + /*--md-code-hl-comment-color: #959077; !* Comments *!*/ + /*--md-code-hl-generic-color: #a6e22e; !* Inserted / green accents *!*/ + /*--md-code-hl-variable-color: #f8f8f2; !* Variables (default to foreground) *!*/ + +} + +/* Light theme - define fd variables and map to md variables */ +[data-md-color-scheme="default"] { + --md-typeset-a-color: var(--brand-color); + /* Map to MkDocs Material variables */ + /*--md-default-bg-color: hsl(var(--fd-background));*/ + /*--md-default-fg-color: var(--fd-muted-foreground);*/ + /*--md-default-fg-color--light: hsl(var(--fd-foreground));*/ + /*--md-default-fg-color--lighter: hsl(var(--fd-foreground) / 0.5);*/ + /*--md-default-fg-color--lightest: hsl(var(--fd-foreground) / 0.07);*/ + /*--md-code-bg-color: hsl(var(--fd-muted));*/ + /*--md-code-fg-color: hsl(var(--fd-foreground));*/ + /*--md-accent-fg-color: hsl(var(--fd-accent-foreground));*/ + /*--md-accent-bg-color: hsl(var(--fd-accent));*/ + /*--md-primary-fg-color: hsl(var(--fd-primary));*/ + /*--md-primary-bg-color: hsl(var(--fd-foreground));*/ +} + + +.md-typeset { + + font-size: 16px !important; + font-weight: 300; + + + h1 { + color: var(--font-foreground-color); + font-weight: 700; + } + + h2 { + color: var(--font-foreground-color); + font-weight: 600; + } + + h3 { + color: var(--font-foreground-color); + font-weight: 600; + } +} + +.md-nav__title { + color: var(--font-foreground-color); +} + +.md-typeset a { + color: var(--brand-color) !important; +} + +.md-nav__item { + font-weight: 300; +} + +.md-nav__item--active, .md-nav__link--active, .md-tabs__item--active { + font-weight: 600; + color: var(--font-foreground-color); +} + +.autorefs-internal { + font-size: 12px !important; +} + +.md-code__content { + border-radius: 7px !important; + border: var(--border-color) solid 1px; + background-color: var(--code-box-background-color) !important; + font-size: 14px !important; +} + +code:not(.md-code__content) { + color: var(--font-foreground-color) !important; + font-weight: 600; +} + +/*!* Navigation *!*/ +/*.md-nav {*/ +/* font-size: 0.9rem;*/ +/*}*/ + +/*.md-nav__link--active {*/ +/* color: var(--md-accent-fg-color) !important;*/ +/* font-weight: 600;*/ +/*}*/ + +/*.md-nav__item .md-nav__link:hover {*/ +/* color: var(--md-accent-fg-color);*/ +/*}*/ + +/*!* Code blocks *!*/ +/*.highlight pre {*/ +/* border-radius: 6px;*/ +/* padding: 1em;*/ +/*}*/ + +/*!* Admonitions *!*/ +/*.md-typeset .admonition {*/ +/* border-radius: 6px;*/ +/* border-left: 4px solid var(--md-accent-fg-color);*/ +/*}*/ + +/*!* Tables *!*/ +/*.md-typeset table:not([class]) {*/ +/* border-radius: 6px;*/ +/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);*/ +/*}*/ + +/*!* Cards *!*/ +/*.md-typeset .grid {*/ +/* grid-gap: 1rem;*/ +/*}*/ + +/*.md-typeset .grid > .card {*/ +/* border-radius: 6px;*/ +/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);*/ +/* background-color: var(--md-code-bg-color);*/ +/* border: 1px solid rgba(255, 255, 255, 0.05);*/ +/*}*/ \ No newline at end of file diff --git a/python/mkdocs.yml b/python/mkdocs.yml index 179871de0..1c42caf8b 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -21,12 +21,16 @@ theme: icon: material/brightness-4 name: Switch to light mode logo: https://avatars.githubusercontent.com/u/105525178?s=200&v=4 + font: + text: IBM Plex Sans + code: IBM Plex Mono features: - navigation.tabs - navigation.sections - toc.follow - navigation.top - search.suggest + - content.code.copy extra: version: @@ -97,3 +101,7 @@ markdown_extensions: - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences + + +extra_css: + - stylesheets/extra.css \ No newline at end of file From c36c1b868e6e0d2326ebf527bb4b6dce09fabb89 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Tue, 26 Aug 2025 10:36:39 -0700 Subject: [PATCH 18/25] updating styling to match fumadocs --- python/docs/overrides/partials/logo.html | 2 + python/docs/sift_logo_dark.svg | 3 + python/docs/sift_logo_light.svg | 3 + python/docs/stylesheets/extra.css | 168 +++++++++++------------ python/mkdocs.yml | 3 +- 5 files changed, 92 insertions(+), 87 deletions(-) create mode 100644 python/docs/overrides/partials/logo.html create mode 100644 python/docs/sift_logo_dark.svg create mode 100644 python/docs/sift_logo_light.svg diff --git a/python/docs/overrides/partials/logo.html b/python/docs/overrides/partials/logo.html new file mode 100644 index 000000000..a7553e811 --- /dev/null +++ b/python/docs/overrides/partials/logo.html @@ -0,0 +1,2 @@ +logo +logo \ No newline at end of file diff --git a/python/docs/sift_logo_dark.svg b/python/docs/sift_logo_dark.svg new file mode 100644 index 000000000..13596ce75 --- /dev/null +++ b/python/docs/sift_logo_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/python/docs/sift_logo_light.svg b/python/docs/sift_logo_light.svg new file mode 100644 index 000000000..75e3f8bdb --- /dev/null +++ b/python/docs/sift_logo_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css index 0a2e01bdf..268c61b82 100644 --- a/python/docs/stylesheets/extra.css +++ b/python/docs/stylesheets/extra.css @@ -1,46 +1,40 @@ /* MkDocs Material Dark Theme Overrides - Fumadocs Style */ -/*.dark {*/ -/* --fd-background: 0 0% 8.04%;*/ -/* --fd-foreground: 0 0% 92%;*/ -/* --fd-muted: 0 0% 12.9%;*/ -/* --fd-muted-foreground: 0 0% 60.9%;*/ -/* --fd-popover: 0 0% 9.8%;*/ -/* --fd-popover-foreground: 0 0% 88%;*/ -/* --fd-card: 0 0% 9.8%;*/ -/* --fd-card-foreground: 0 0% 98%;*/ -/* --fd-border: 0 0% 14%;*/ -/* --fd-primary: 0 0% 98%;*/ -/* --fd-primary-foreground: 0 0% 9%;*/ -/* --fd-secondary: 0 0% 12.9%;*/ -/* --fd-secondary-foreground: 0 0% 98%;*/ -/* --fd-accent: 0 0% 16.9%;*/ -/* --fd-accent-foreground: 0 0% 90%;*/ -/* --fd-ring: 0 0% 14.9%;*/ -/*}*/ +:root { + --tomato-1: #f9f6f5; + --tomato-2: #f9f2f0; + --tomato-3: #f9e4df; + --tomato-4: #ffd4ca; + --tomato-5: #fec4b7; + --tomato-6: #f9b3a4; + --tomato-7: #f19e8c; + --tomato-8: #e9826d; + --tomato-9: #ee4220; + --tomato-10: #e03006; + --tomato-11: #c82700; + --tomato-12: #5f2519; + --tomato-a1: #96612e05; + --tomato-a2: #c947140a; + --tomato-a3: #e933041b; + --tomato-a4: #ffd4ca; + --tomato-a5: #ffb3a2c0; + --tomato-a6: #f62f0358; + --tomato-a7: #e42a0170; + --tomato-a8: #dc270290; + --tomato-a9: #ed2801df; + --tomato-a10: #df2b00f9; + --tomato-a11: #c82700; + --tomato-a12: #4e0e01e6; + + --brand-color: var(--tomato-9); +} -/*.light {*/ -/* --fd-background: 0 0% 96%;*/ -/* --fd-foreground: 0 0% 3.9%;*/ -/* --fd-muted: 0 0% 96.1%;*/ -/* --fd-muted-foreground: 0 0% 45.1%;*/ -/* --fd-popover: 0 0% 98%;*/ -/* --fd-popover-foreground: 0 0% 15.1%;*/ -/* --fd-card: 0 0% 94.7%;*/ -/* --fd-card-foreground: 0 0% 3.9%;*/ -/* --fd-border: 0 0% 89.8%;*/ -/* --fd-primary: 0 0% 9%;*/ -/* --fd-primary-foreground: 0 0% 98%;*/ -/* --fd-secondary: 0 0% 93.1%;*/ -/* --fd-secondary-foreground: 0 0% 9%;*/ -/* --fd-accent: 0 0% 90.1%;*/ -/* --fd-accent-foreground: 0 0% 9%;*/ -/* --fd-ring: 0 0% 63.9%;*/ -/*}*/ +#logo_light_mode { + display: var(--md-footer-logo-light-mode); +} -/* Brand Colors */ -:root { - --brand-color: #ee4220; +#logo_dark_mode { + display: var(--md-footer-logo-dark-mode); } /* Dark theme - define fd variables and map to md variables */ @@ -52,55 +46,34 @@ --font-foreground-color: rgb(255, 255, 255); --border-color: rgb(36, 36, 36); --code-box-background-color: rgb(18, 18, 18); - /*--md-default-fg-color: var(--fd-muted-foreground);*/ - /*--md-typeset-color: var(--fd-muted-foreground);*/ - /*--md-default-fg-color--light: hsl(var(--fd-foreground));*/ - /*--md-default-fg-color--lighter: hsl(var(--fd-foreground) / 0.5);*/ - /*--md-default-fg-color--lightest: hsl(var(--fd-foreground) / 0.07);*/ - /*--md-code-bg-color: hsl(var(--fd-muted));*/ - /*--md-code-fg-color: hsl(var(--fd-foreground));*/ - /*--md-accent-fg-color: hsl(var(--fd-accent-foreground));*/ - /*--md-accent-bg-color: hsl(var(--fd-accent));*/ - /*--md-primary-fg-color: hsl(var(--fd-primary));*/ - /*--md-primary-bg-color: hsl(var(--fd-foreground));*/ - - /* monokai */ - /*--md-code-fg-color: #f8f8f2; !* Default text *!*/ - /*--md-code-bg-color: #272822; !* Background *!*/ - /*--md-code-hl-color: #49483e; !* Highlighted line background *!*/ - - /*--md-code-hl-number-color: #ae81ff; !* Number *!*/ - /*--md-code-hl-special-color: #ff4689; !* Special (tags, deleted, prompt) *!*/ - /*--md-code-hl-function-color: #a6e22e; !* Function, class, decorator, etc. *!*/ - /*--md-code-hl-constant-color: #66d9ef; !* Constants, attributes *!*/ - /*--md-code-hl-keyword-color: #66d9ef; !* Keywords *!*/ - /*--md-code-hl-string-color: #e6db74; !* Strings *!*/ - /*--md-code-hl-name-color: #f8f8f2; !* Generic names *!*/ - /*--md-code-hl-operator-color: #ff4689; !* Operators *!*/ - /*--md-code-hl-punctuation-color: #f8f8f2; !* Punctuation *!*/ - /*--md-code-hl-comment-color: #959077; !* Comments *!*/ - /*--md-code-hl-generic-color: #a6e22e; !* Inserted / green accents *!*/ - /*--md-code-hl-variable-color: #f8f8f2; !* Variables (default to foreground) *!*/ + --md-primary-bg-color: var(--font-foreground-color); + --header-bg-color: hsl(0 0% 8.04%/.8); + --md-footer-logo-dark-mode: block; + --md-footer-logo-light-mode: none; } /* Light theme - define fd variables and map to md variables */ [data-md-color-scheme="default"] { - --md-typeset-a-color: var(--brand-color); - /* Map to MkDocs Material variables */ - /*--md-default-bg-color: hsl(var(--fd-background));*/ - /*--md-default-fg-color: var(--fd-muted-foreground);*/ - /*--md-default-fg-color--light: hsl(var(--fd-foreground));*/ - /*--md-default-fg-color--lighter: hsl(var(--fd-foreground) / 0.5);*/ - /*--md-default-fg-color--lightest: hsl(var(--fd-foreground) / 0.07);*/ - /*--md-code-bg-color: hsl(var(--fd-muted));*/ - /*--md-code-fg-color: hsl(var(--fd-foreground));*/ - /*--md-accent-fg-color: hsl(var(--fd-accent-foreground));*/ - /*--md-accent-bg-color: hsl(var(--fd-accent));*/ - /*--md-primary-fg-color: hsl(var(--fd-primary));*/ - /*--md-primary-bg-color: hsl(var(--fd-foreground));*/ + --md-default-bg-color: rgb(255, 255, 255); + --md-typeset-a-color: var(--brand-color) !important; + --font-foreground-color: rgb(10, 10, 10); + --border-color: rgb(229, 229, 229); + --code-box-background-color: rgba(237, 237, 237, 0.5); + --md-primary-bg-color: var(--font-foreground-color); + --header-bg-color: hsl(0 0% 96%/.8); + --md-footer-logo-dark-mode: none; + --md-footer-logo-light-mode: block; +} + +.md-header__title { + margin-left: 2px !important; } +.md-header, .md-tabs { + background-color: var(--header-bg-color) !important; + box-shadow: none !important; +} .md-typeset { @@ -126,10 +99,11 @@ .md-nav__title { color: var(--font-foreground-color); + background-color: var(--md-default-bg-color) !important; } -.md-typeset a { - color: var(--brand-color) !important; +.md-typeset a:hover { + text-decoration: underline; } .md-nav__item { @@ -152,11 +126,33 @@ font-size: 14px !important; } -code:not(.md-code__content) { - color: var(--font-foreground-color) !important; - font-weight: 600; +.md-tabs, .md-header--shadow { + border-bottom: var(--border-color) solid 1px; } +.md-sidebar--primary { + border-right: var(--border-color) solid 1px; +} + +.md-header__button.md-logo { + > img { + height: 2rem !important; + } + + margin: 0 !important; + padding: 0 !important; +} + +.md-search__input { + +} + + +/*code:not(.md-code__content) {*/ +/* color: var(--font-foreground-color) !important;*/ +/* font-weight: 600;*/ +/*}*/ + /*!* Navigation *!*/ /*.md-nav {*/ /* font-size: 0.9rem;*/ diff --git a/python/mkdocs.yml b/python/mkdocs.yml index 1c42caf8b..847818962 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -20,7 +20,8 @@ theme: toggle: icon: material/brightness-4 name: Switch to light mode - logo: https://avatars.githubusercontent.com/u/105525178?s=200&v=4 + logo_light_mode: sift_logo_dark.svg + logo_dark_mode: sift_logo_light.svg font: text: IBM Plex Sans code: IBM Plex Mono From a61b6eb5d6635b2c43e6859f0df195af8eafba12 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Tue, 26 Aug 2025 18:59:54 -0700 Subject: [PATCH 19/25] theme update --- python/docs/stylesheets/extra.css | 62 +++++++++++++++++++++++++++---- python/mkdocs.yml | 29 +++++++++++---- 2 files changed, 76 insertions(+), 15 deletions(-) diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css index 268c61b82..24f4bd917 100644 --- a/python/docs/stylesheets/extra.css +++ b/python/docs/stylesheets/extra.css @@ -27,6 +27,11 @@ --tomato-a12: #4e0e01e6; --brand-color: var(--tomato-9); + + --md-accent-fg-color: var(--brand-color); + --md-accent-fg-color--transparent: rgb(from var(--brand-color) r g b / 0.1); + --md-accent-bg-color: hsla(0, 0%, 100%, 1); + --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); } #logo_light_mode { @@ -39,37 +44,64 @@ /* Dark theme - define fd variables and map to md variables */ [data-md-color-scheme="slate"] { + /*--md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);*/ + /*--md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-400)}, 1);*/ + /*--md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1);*/ + /*--md-primary-bg-color: hsla(0, 0%, 100%, 1);*/ + --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); + + /* Logo */ + --md-footer-logo-dark-mode: block; + --md-footer-logo-light-mode: none; + /* Define your color variables */ /* Map to MkDocs Material variables */ + --header-bg-color: hsl(0 0% 8.04%/.8); + --bold-header-color: white; --md-default-bg-color: rgb(0, 0, 0); --md-typeset-a-color: var(--brand-color) !important; --font-foreground-color: rgb(255, 255, 255); + --border-color: rgb(36, 36, 36); --code-box-background-color: rgb(18, 18, 18); --md-primary-bg-color: var(--font-foreground-color); - --header-bg-color: hsl(0 0% 8.04%/.8); - --md-footer-logo-dark-mode: block; - --md-footer-logo-light-mode: none; + + --search-bg: rgba(237, 237, 237, 0); + } /* Light theme - define fd variables and map to md variables */ [data-md-color-scheme="default"] { + /* Logo */ + --md-footer-logo-dark-mode: none; + --md-footer-logo-light-mode: block; + + /* Define your color variables */ + /* Map to MkDocs Material variables */ + --header-bg-color: hsl(0 0% 96%/.8); + --bold-header-color: black; --md-default-bg-color: rgb(255, 255, 255); --md-typeset-a-color: var(--brand-color) !important; --font-foreground-color: rgb(10, 10, 10); + --border-color: rgb(229, 229, 229); --code-box-background-color: rgba(237, 237, 237, 0.5); --md-primary-bg-color: var(--font-foreground-color); - --header-bg-color: hsl(0 0% 96%/.8); - --md-footer-logo-dark-mode: none; - --md-footer-logo-light-mode: block; + + --search-bg: rgba(237, 237, 237, 0); + + } .md-header__title { margin-left: 2px !important; } +.md-header__topic { + color: var(--bold-header-color) !important; +} + .md-header, .md-tabs { background-color: var(--header-bg-color) !important; box-shadow: none !important; @@ -97,11 +129,19 @@ } } +.md-main__inner { + margin-top: 0 !important; +} + .md-nav__title { color: var(--font-foreground-color); background-color: var(--md-default-bg-color) !important; } +.md-nav__source { + background-color: var(--md-default-bg-color) !important; +} + .md-typeset a:hover { text-decoration: underline; } @@ -132,6 +172,7 @@ .md-sidebar--primary { border-right: var(--border-color) solid 1px; + height: 100%; } .md-header__button.md-logo { @@ -143,8 +184,15 @@ padding: 0 !important; } -.md-search__input { +.md-search__input, .md-search__suggest, .md-search__form { + background-color: var(--search-bg) !important; + border-radius: 0.5rem !important; + border: var(--border-color) solid 1px; + ::placeholder { + color: var(--font-foreground-color) !important; + font-weight: 300; + } } diff --git a/python/mkdocs.yml b/python/mkdocs.yml index 847818962..f74ede9d0 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Sift Python Client Library +site_name: Sift | Python Client Library site_url: https://sift-stack.github.io/sift/python/ repo_url: https://github.com/sift-stack/sift/tree/main/python copyright: "Copyright 2025 Sift Stack, Inc." @@ -6,29 +6,42 @@ theme: name: material custom_dir: docs/overrides palette: + # Palette toggle for automatic mode + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode # Palette toggle for light mode - - scheme: default - primary: grey - accent: deep orange + - media: "(prefers-color-scheme: light)" + scheme: default + primary: custom + accent: custom toggle: icon: material/brightness-7 name: Switch to dark mode # Palette toggle for dark mode - - scheme: slate - primary: black - accent: deep orange + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: custom + accent: custom toggle: icon: material/brightness-4 - name: Switch to light mode + name: Switch to system preference logo_light_mode: sift_logo_dark.svg logo_dark_mode: sift_logo_light.svg + theme: + favicon: sift_logo_light.svg font: text: IBM Plex Sans code: IBM Plex Mono features: + - navigation.instant - navigation.tabs - navigation.sections + - navigation.tracking + - navigation.prune - toc.follow + # - toc.integrate - navigation.top - search.suggest - content.code.copy From 9491dd086103787809208b207a11b61e43e6a7d7 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 27 Aug 2025 10:31:18 -0700 Subject: [PATCH 20/25] banner clean up --- python/docs/index.md | 6 ++-- python/docs/stylesheets/extra.css | 59 ++++--------------------------- python/mkdocs.yml | 3 ++ 3 files changed, 12 insertions(+), 56 deletions(-) diff --git a/python/docs/index.md b/python/docs/index.md index 40e38f2db..a177f1054 100644 --- a/python/docs/index.md +++ b/python/docs/index.md @@ -17,7 +17,7 @@ pip install sift-stack-py This documentation covers two Python APIs for interacting with Sift: -### Sift Py API (Legacy) +### Sift Py API The original low-level Python API that provides direct access to Sift's protocol buffer interfaces. @@ -49,13 +49,13 @@ Explore the [**Sift Client API (New)**][sift_client] section for the complete AP - **Modern Patterns** - Context managers, iterators, and Python best practices -## Getting Help +## Getting help - **API Reference** - Browse the complete API documentation in the navigation - **Examples** - Check out code examples throughout the documentation - **GitHub** - Visit our [repository](https://github.com/sift-stack/sift) for issues and contributions -## What's Next? +## What's next? Ready to dive deeper? Explore the API documentation to learn about: diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css index 24f4bd917..ee4f936b3 100644 --- a/python/docs/stylesheets/extra.css +++ b/python/docs/stylesheets/extra.css @@ -155,10 +155,6 @@ color: var(--font-foreground-color); } -.autorefs-internal { - font-size: 12px !important; -} - .md-code__content { border-radius: 7px !important; border: var(--border-color) solid 1px; @@ -195,52 +191,9 @@ } } - -/*code:not(.md-code__content) {*/ -/* color: var(--font-foreground-color) !important;*/ -/* font-weight: 600;*/ -/*}*/ - -/*!* Navigation *!*/ -/*.md-nav {*/ -/* font-size: 0.9rem;*/ -/*}*/ - -/*.md-nav__link--active {*/ -/* color: var(--md-accent-fg-color) !important;*/ -/* font-weight: 600;*/ -/*}*/ - -/*.md-nav__item .md-nav__link:hover {*/ -/* color: var(--md-accent-fg-color);*/ -/*}*/ - -/*!* Code blocks *!*/ -/*.highlight pre {*/ -/* border-radius: 6px;*/ -/* padding: 1em;*/ -/*}*/ - -/*!* Admonitions *!*/ -/*.md-typeset .admonition {*/ -/* border-radius: 6px;*/ -/* border-left: 4px solid var(--md-accent-fg-color);*/ -/*}*/ - -/*!* Tables *!*/ -/*.md-typeset table:not([class]) {*/ -/* border-radius: 6px;*/ -/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);*/ -/*}*/ - -/*!* Cards *!*/ -/*.md-typeset .grid {*/ -/* grid-gap: 1rem;*/ -/*}*/ - -/*.md-typeset .grid > .card {*/ -/* border-radius: 6px;*/ -/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);*/ -/* background-color: var(--md-code-bg-color);*/ -/* border: 1px solid rgba(255, 255, 255, 0.05);*/ -/*}*/ \ No newline at end of file +.md-banner--warning { + .md-banner__inner { + font-size: 14px !important; + margin: 0; + } +} \ No newline at end of file diff --git a/python/mkdocs.yml b/python/mkdocs.yml index f74ede9d0..37ec2e520 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -107,6 +107,9 @@ plugins: markdown_extensions: - admonition + - toc: + permalink: true + title: On this page - pymdownx.details - pymdownx.highlight: anchor_linenums: true From f410aeb54deb9bba571bd5099a0c69f0e1bb3338 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 27 Aug 2025 10:39:34 -0700 Subject: [PATCH 21/25] add favicon, stylesheet cleanup --- python/docs/stylesheets/extra.css | 139 +++++++++++------- python/docs/stylesheets/sift-favicon.ico | Bin 0 -> 4286 bytes .../docs/{ => stylesheets}/sift_logo_dark.svg | 0 .../{ => stylesheets}/sift_logo_light.svg | 0 python/mkdocs.yml | 7 +- 5 files changed, 92 insertions(+), 54 deletions(-) create mode 100644 python/docs/stylesheets/sift-favicon.ico rename python/docs/{ => stylesheets}/sift_logo_dark.svg (100%) rename python/docs/{ => stylesheets}/sift_logo_light.svg (100%) diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css index ee4f936b3..495252b7a 100644 --- a/python/docs/stylesheets/extra.css +++ b/python/docs/stylesheets/extra.css @@ -28,12 +28,17 @@ --brand-color: var(--tomato-9); + /* MkDocs Material Accent Colors */ --md-accent-fg-color: var(--brand-color); --md-accent-fg-color--transparent: rgb(from var(--brand-color) r g b / 0.1); --md-accent-bg-color: hsla(0, 0%, 100%, 1); --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); } +/* ============================================================================= + LOGO DISPLAY CONTROLS + ============================================================================= */ + #logo_light_mode { display: var(--md-footer-logo-light-mode); } @@ -42,56 +47,65 @@ display: var(--md-footer-logo-dark-mode); } -/* Dark theme - define fd variables and map to md variables */ +/* ============================================================================= + DARK THEME VARIABLES + ============================================================================= */ + [data-md-color-scheme="slate"] { - /*--md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);*/ - /*--md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-400)}, 1);*/ - /*--md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1);*/ - /*--md-primary-bg-color: hsla(0, 0%, 100%, 1);*/ + /* Primary Colors */ --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); + --md-default-bg-color: rgb(0, 0, 0); + --md-primary-bg-color: var(--font-foreground-color); - /* Logo */ + /* Logo Display */ --md-footer-logo-dark-mode: block; --md-footer-logo-light-mode: none; - /* Define your color variables */ - /* Map to MkDocs Material variables */ + /* Custom Theme Colors */ --header-bg-color: hsl(0 0% 8.04%/.8); --bold-header-color: white; - --md-default-bg-color: rgb(0, 0, 0); - --md-typeset-a-color: var(--brand-color) !important; --font-foreground-color: rgb(255, 255, 255); - --border-color: rgb(36, 36, 36); --code-box-background-color: rgb(18, 18, 18); - --md-primary-bg-color: var(--font-foreground-color); - --search-bg: rgba(237, 237, 237, 0); - + /* Link Colors */ + --md-typeset-a-color: var(--brand-color) !important; } -/* Light theme - define fd variables and map to md variables */ +/* ============================================================================= + LIGHT THEME VARIABLES + ============================================================================= */ + [data-md-color-scheme="default"] { - /* Logo */ + /* Primary Colors */ + --md-primary-bg-color--light: hsla(0, 0%, 0%, 0.7); + --md-default-bg-color: rgb(255, 255, 255); + --md-primary-bg-color: var(--font-foreground-color); + + /* Logo Display */ --md-footer-logo-dark-mode: none; --md-footer-logo-light-mode: block; - /* Define your color variables */ - /* Map to MkDocs Material variables */ + /* Custom Theme Colors */ --header-bg-color: hsl(0 0% 96%/.8); --bold-header-color: black; - --md-default-bg-color: rgb(255, 255, 255); - --md-typeset-a-color: var(--brand-color) !important; --font-foreground-color: rgb(10, 10, 10); - --border-color: rgb(229, 229, 229); --code-box-background-color: rgba(237, 237, 237, 0.5); - --md-primary-bg-color: var(--font-foreground-color); - --search-bg: rgba(237, 237, 237, 0); + /* Link Colors */ + --md-typeset-a-color: var(--brand-color) !important; +} + +/* ============================================================================= + HEADER STYLES + ============================================================================= */ +.md-header, .md-tabs { + background-color: var(--header-bg-color) !important; + box-shadow: none !important; } .md-header__title { @@ -102,17 +116,31 @@ color: var(--bold-header-color) !important; } -.md-header, .md-tabs { - background-color: var(--header-bg-color) !important; - box-shadow: none !important; +.md-tabs, .md-header--shadow { + border-bottom: var(--border-color) solid 1px; } -.md-typeset { +/* ============================================================================= + LOGO STYLES + ============================================================================= */ + +.md-header__button.md-logo { + margin: 0 !important; + padding: 0 !important; + + > img { + height: 2rem !important; + } +} +/* ============================================================================= + TYPOGRAPHY STYLES + ============================================================================= */ + +.md-typeset { font-size: 16px !important; font-weight: 300; - h1 { color: var(--font-foreground-color); font-weight: 700; @@ -129,10 +157,14 @@ } } -.md-main__inner { - margin-top: 0 !important; +.md-typeset a:hover { + text-decoration: underline; } +/* ============================================================================= + NAVIGATION STYLES + ============================================================================= */ + .md-nav__title { color: var(--font-foreground-color); background-color: var(--md-default-bg-color) !important; @@ -142,10 +174,6 @@ background-color: var(--md-default-bg-color) !important; } -.md-typeset a:hover { - text-decoration: underline; -} - .md-nav__item { font-weight: 300; } @@ -155,31 +183,38 @@ color: var(--font-foreground-color); } -.md-code__content { - border-radius: 7px !important; - border: var(--border-color) solid 1px; - background-color: var(--code-box-background-color) !important; - font-size: 14px !important; -} - -.md-tabs, .md-header--shadow { - border-bottom: var(--border-color) solid 1px; -} +/* ============================================================================= + SIDEBAR STYLES + ============================================================================= */ .md-sidebar--primary { border-right: var(--border-color) solid 1px; height: 100%; } -.md-header__button.md-logo { - > img { - height: 2rem !important; - } +/* ============================================================================= + LAYOUT STYLES + ============================================================================= */ - margin: 0 !important; - padding: 0 !important; +.md-main__inner { + margin-top: 0 !important; } +/* ============================================================================= + CODE BLOCK STYLES + ============================================================================= */ + +.md-code__content { + border-radius: 7px !important; + border: var(--border-color) solid 1px; + background-color: var(--code-box-background-color) !important; + font-size: 14px !important; +} + +/* ============================================================================= + SEARCH STYLES + ============================================================================= */ + .md-search__input, .md-search__suggest, .md-search__form { background-color: var(--search-bg) !important; border-radius: 0.5rem !important; @@ -191,6 +226,10 @@ } } +/* ============================================================================= + BANNER STYLES + ============================================================================= */ + .md-banner--warning { .md-banner__inner { font-size: 14px !important; diff --git a/python/docs/stylesheets/sift-favicon.ico b/python/docs/stylesheets/sift-favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..47e2cd32ef6fc6b465b101ac6ba3fbf8d46c0b6e GIT binary patch literal 4286 zcmeI0ze~eF6o6l;TAeB=9YkqCM8QQJ#H}qjIk-58gMtqJ18#ye_#X(aE+VLl=-{GI zI*5}fxCNpIlD#w;XhfWJF{HFi8Ql z{a0AqN72+pDJ3!S4B~6R_ZmnrpBdPJ8+e2}D8nWUK~(!_l-$?gCsh`=AO$x2SRmg! z1eGfsGhm~KCGva+Eo}JRqW3~8J64(XJ^iU+uZMLuxcZA*sVS1Rr|INtJ zs=7ylb_mjgp1IB1_1-T~27G$xV{Hx2;5;Hu$-4|45M&nr>C;J%i?A9oE9B3D*Rl3s z-+)huLXJt=4_>uR+Y~;}mK$)$r=KTg9Y1{--xo_gY=@|8_B2UcnCF03ySo^}9Jg6t z>$C9Xl{kP+pYNdep~kxA?|JfseJ-33V{_jZ$oB+)iSE;ZB$&rwL)ZIr9Uh=jJ}?}@ zIM}G=mqTAqgHVKN7z3NL_NyJQMSp(d8Am^3wv2~3c`Bz>O;V~VN##mHy^5%Nky1q@ j&-;V4j>0A`uNZ2AleRffkt~jR7E8)yi`Mkt5^wndl`&iO literal 0 HcmV?d00001 diff --git a/python/docs/sift_logo_dark.svg b/python/docs/stylesheets/sift_logo_dark.svg similarity index 100% rename from python/docs/sift_logo_dark.svg rename to python/docs/stylesheets/sift_logo_dark.svg diff --git a/python/docs/sift_logo_light.svg b/python/docs/stylesheets/sift_logo_light.svg similarity index 100% rename from python/docs/sift_logo_light.svg rename to python/docs/stylesheets/sift_logo_light.svg diff --git a/python/mkdocs.yml b/python/mkdocs.yml index 37ec2e520..e598f2d8d 100644 --- a/python/mkdocs.yml +++ b/python/mkdocs.yml @@ -5,6 +5,7 @@ copyright: "Copyright 2025 Sift Stack, Inc." theme: name: material custom_dir: docs/overrides + favicon: stylesheets/sift-favicon.ico palette: # Palette toggle for automatic mode - media: "(prefers-color-scheme)" @@ -27,10 +28,8 @@ theme: toggle: icon: material/brightness-4 name: Switch to system preference - logo_light_mode: sift_logo_dark.svg - logo_dark_mode: sift_logo_light.svg - theme: - favicon: sift_logo_light.svg + logo_light_mode: stylesheets/sift_logo_dark.svg + logo_dark_mode: stylesheets/sift_logo_light.svg font: text: IBM Plex Sans code: IBM Plex Mono From a85e7264d6adcaa35ee7a5da8b4aec77a3a54bb2 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 27 Aug 2025 10:48:30 -0700 Subject: [PATCH 22/25] banner cleanup --- python/docs/stylesheets/extra.css | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css index 495252b7a..082d83f65 100644 --- a/python/docs/stylesheets/extra.css +++ b/python/docs/stylesheets/extra.css @@ -230,9 +230,6 @@ BANNER STYLES ============================================================================= */ -.md-banner--warning { - .md-banner__inner { - font-size: 14px !important; - margin: 0; - } +.md-banner__inner { + margin: 0; } \ No newline at end of file From b0a73c5c7289ecd83e249e9fb4bfd87b0d917d1e Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 27 Aug 2025 10:56:32 -0700 Subject: [PATCH 23/25] banner cleanup --- python/docs/stylesheets/extra.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/docs/stylesheets/extra.css b/python/docs/stylesheets/extra.css index 082d83f65..92b39513c 100644 --- a/python/docs/stylesheets/extra.css +++ b/python/docs/stylesheets/extra.css @@ -231,5 +231,6 @@ ============================================================================= */ .md-banner__inner { - margin: 0; + margin-top: 0; + margin-bottom: 0; } \ No newline at end of file From 7d81490bc7eca7582916b56b3828b3416f6b1b70 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 27 Aug 2025 14:37:07 -0700 Subject: [PATCH 24/25] Update actions checkout to only one version --- .github/workflows/python_build_docs.yml | 10 ++++++++-- .github/workflows/python_release.yaml | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_build_docs.yml b/.github/workflows/python_build_docs.yml index ab6940b2b..8e167ab98 100644 --- a/.github/workflows/python_build_docs.yml +++ b/.github/workflows/python_build_docs.yml @@ -26,7 +26,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Fetch full history for mike + fetch-depth: 1 - name: Set up Python uses: actions/setup-python@v4 @@ -56,6 +56,9 @@ jobs: echo "alias=$ALIAS" >> $GITHUB_OUTPUT echo "Dev deployment - Version: $VERSION, Alias: $ALIAS" + - name: Fetch gh-pages branch + run: git fetch origin gh-pages --depth=1 + - name: Configure Git run: | git config --global user.name "github-actions[bot]" @@ -78,7 +81,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Fetch full history for mike + fetch-depth: 1 - name: Set up Python uses: actions/setup-python@v4 @@ -89,6 +92,9 @@ jobs: run: | cd python pip install -e .[docs] + + - name: Fetch gh-pages branch + run: git fetch origin gh-pages --depth=1 - name: Configure Git run: | diff --git a/.github/workflows/python_release.yaml b/.github/workflows/python_release.yaml index 278475fa3..247d19e33 100644 --- a/.github/workflows/python_release.yaml +++ b/.github/workflows/python_release.yaml @@ -98,7 +98,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Fetch full history for mike + fetch-depth: 1 - name: Set up Python uses: actions/setup-python@v4 @@ -147,6 +147,9 @@ jobs: echo "hidden=$HIDDEN" >> $GITHUB_OUTPUT echo "Final - Version: $VERSION, Alias: $ALIAS, Hidden: $HIDDEN" + - name: Fetch gh-pages branch + run: git fetch origin gh-pages --depth=1 + - name: Configure Git run: | git config --global user.name "github-actions[bot]" From 15cc847ac80e5be5232a8097782e3530fca871e4 Mon Sep 17 00:00:00 2001 From: Alex Luck Date: Wed, 27 Aug 2025 15:43:32 -0700 Subject: [PATCH 25/25] update docs dependencies options --- .github/workflows/python_build_docs.yml | 4 ++-- .github/workflows/python_release.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_build_docs.yml b/.github/workflows/python_build_docs.yml index 8e167ab98..912cb3d33 100644 --- a/.github/workflows/python_build_docs.yml +++ b/.github/workflows/python_build_docs.yml @@ -36,7 +36,7 @@ jobs: - name: Install dependencies run: | cd python - pip install -e .[docs] + pip install -e .[docs,development] - name: Extract version id: version @@ -91,7 +91,7 @@ jobs: - name: Install dependencies run: | cd python - pip install -e .[docs] + pip install -e .[docs,development] - name: Fetch gh-pages branch run: git fetch origin gh-pages --depth=1 diff --git a/.github/workflows/python_release.yaml b/.github/workflows/python_release.yaml index 247d19e33..7c1e855b0 100644 --- a/.github/workflows/python_release.yaml +++ b/.github/workflows/python_release.yaml @@ -108,7 +108,7 @@ jobs: - name: Install dependencies run: | cd python - pip install -e .[docs] + pip install -e .[docs,development] - name: Extract version and check if stable id: version