Rename the import package app to fluksio
A wheel whose top-level module is `app` collides with anything else in a user's venv, so the package that is about to be published takes the name it is published under. Only the Python package moves; the repo, the Docker WORKDIR and the compose project keep theirs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -49,5 +49,5 @@ jobs:
|
||||
# The hooks cover ruff and biome but not mypy, which `make lint-backend`
|
||||
# runs and which is strict for everything outside the flow prototypes.
|
||||
- name: Typecheck backend
|
||||
run: uv run mypy app
|
||||
run: uv run mypy fluksio
|
||||
working-directory: backend
|
||||
|
||||
@@ -13,7 +13,7 @@ repos:
|
||||
exclude: |
|
||||
(?x)^(
|
||||
frontend/src/client/.*|
|
||||
backend/app/email-templates/build/.*
|
||||
backend/fluksio/email-templates/build/.*
|
||||
)$
|
||||
- id: trailing-whitespace
|
||||
exclude: ^frontend/src/client/.*
|
||||
|
||||
@@ -83,7 +83,7 @@ install: ## Install all dependencies (backend + frontend)
|
||||
cd frontend && bun install
|
||||
|
||||
dev-backend: ## Start the FastAPI backend with hot-reload (local)
|
||||
cd backend && uv run fastapi dev app/main.py
|
||||
cd backend && uv run fastapi dev fluksio/main.py
|
||||
|
||||
dev-frontend: ## Start the Vite dev server (local)
|
||||
cd frontend && bun dev
|
||||
@@ -169,7 +169,7 @@ lint: lint-backend lint-frontend ## Run all linters
|
||||
lint-backend: ## Lint backend with ruff + mypy
|
||||
cd backend && uv run ruff check .
|
||||
cd backend && uv run ruff format --check .
|
||||
cd backend && uv run mypy app
|
||||
cd backend && uv run mypy fluksio
|
||||
|
||||
lint-frontend: ## Lint frontend with biome
|
||||
cd frontend && bun run lint
|
||||
|
||||
@@ -11,7 +11,7 @@ repo holds the FastAPI backend, the flow engine, and the dashboard SPA. It is se
|
||||
|
||||
```text
|
||||
backend/ FastAPI + SQLModel + Alembic + Postgres
|
||||
app/flow/ the flow engine (nodes, pipeline, state backends, controller)
|
||||
fluksio/flow/ the flow engine (nodes, pipeline, state backends, controller)
|
||||
frontend/ React 19 + TanStack Router + Tailwind 4 + shadcn/ui
|
||||
docker/ compose.yml → compose.dev.yml → compose.local.yml (+ compose.traefik.yml)
|
||||
scripts/ generate-client.sh, test.sh
|
||||
|
||||
+2
-2
@@ -44,14 +44,14 @@ Python, optimised for development speed. Owns the graph structure, persistence a
|
||||
external interfaces. See `docs/architecture/structure.canvas` → *Backend – Management*.
|
||||
|
||||
- [x] FastAPI + SQLModel + Alembic + Postgres base with JWT auth and user management
|
||||
- [x] Flow engine in `backend/app/flow/`: `Node` / `Pipeline` / `StateBackend`
|
||||
- [x] Flow engine in `backend/fluksio/flow/`: `Node` / `Pipeline` / `StateBackend`
|
||||
(memory + Redis) / `FlowController`
|
||||
- [x] Node types: HTTP, MQTT, InfluxDB, Delay, MLP
|
||||
- [x] Flow-logic vocabulary as node types rather than repeated code: inject (manual,
|
||||
interval, cron or at startup), switch, change, filter-unchanged, join, trigger,
|
||||
command, file and ntfy. Each is configured by filling in a form the editor
|
||||
generates from its parameter schema
|
||||
- [x] `app/flow` is an importable package with absolute `app.flow.*` imports
|
||||
- [x] `fluksio/flow` is an importable package with absolute `fluksio.flow.*` imports
|
||||
- [x] Typed, serializable node I/O: every port declares a `DType`, messages are
|
||||
JSON on the wire and in Redis, no pickle anywhere. Binary codecs are still
|
||||
open — `DType.JSON` carries everything non-scalar for now
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Python
|
||||
__pycache__
|
||||
app.egg-info
|
||||
fluksio.egg-info
|
||||
*.pyc
|
||||
.mypy_cache
|
||||
.coverage
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
*.png
|
||||
__pycache__
|
||||
app.egg-info
|
||||
fluksio.egg-info
|
||||
*.pyc
|
||||
.mypy_cache
|
||||
.coverage
|
||||
|
||||
+4
-4
@@ -25,20 +25,20 @@ ENV PATH="/app/.venv/bin:$PATH"
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||
uv sync --frozen --no-install-workspace --package app
|
||||
uv sync --frozen --no-install-workspace --package fluksio
|
||||
|
||||
COPY ./backend/scripts /app/backend/scripts
|
||||
|
||||
COPY ./backend/pyproject.toml ./backend/alembic.ini /app/backend/
|
||||
|
||||
COPY ./backend/app /app/backend/app
|
||||
COPY ./backend/fluksio /app/backend/fluksio
|
||||
|
||||
# Sync the project
|
||||
# Ref: https://docs.astral.sh/uv/guides/integration/docker/#intermediate-layers
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||
uv sync --frozen --package app
|
||||
uv sync --frozen --package fluksio
|
||||
|
||||
# Connectors are ordinary installed packages found through the
|
||||
# `fluksio.node_types` entry point. `make connectors` builds them into here;
|
||||
@@ -54,4 +54,4 @@ WORKDIR /app/backend/
|
||||
# Single worker on purpose: the process hosts the flow engine, and a second
|
||||
# worker would be a second engine — duplicated subscriptions, cron ticks and
|
||||
# webhooks. Scaling out is the M5 worker split, not more uvicorn processes.
|
||||
CMD ["fastapi", "run", "app/main.py"]
|
||||
CMD ["fastapi", "run", "fluksio/main.py"]
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
[alembic]
|
||||
# path to migration scripts
|
||||
script_location = app/alembic
|
||||
script_location = fluksio/alembic
|
||||
|
||||
# template used to generate migration files
|
||||
# file_template = %%(rev)s_%%(slug)s
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
"""The flow engine: nodes, the pipeline that runs them, and their storage."""
|
||||
|
||||
from app.flow.controller import FlowController, NodeStatus
|
||||
from app.flow.events import EventBus, event_bus
|
||||
from app.flow.messages import DType, MessageSpec, qualify
|
||||
from app.flow.nodes import Node
|
||||
from app.flow.pipeline import Pipeline, ValidationIssue
|
||||
from app.flow.state import MemoryState, RedisState, StateBackend
|
||||
from app.flow.store import FlowStore
|
||||
|
||||
__all__ = [
|
||||
"DType",
|
||||
"EventBus",
|
||||
"FlowController",
|
||||
"FlowStore",
|
||||
"MemoryState",
|
||||
"MessageSpec",
|
||||
"Node",
|
||||
"NodeStatus",
|
||||
"Pipeline",
|
||||
"RedisState",
|
||||
"StateBackend",
|
||||
"ValidationIssue",
|
||||
"event_bus",
|
||||
"qualify",
|
||||
]
|
||||
@@ -1,37 +0,0 @@
|
||||
"""Built-in node types.
|
||||
|
||||
Split by the outside world each one talks to. Importing from
|
||||
``app.flow.nodes`` keeps working, which is what every caller does.
|
||||
"""
|
||||
|
||||
from app.flow.nodes.base import RESERVED_SETTINGS, Node
|
||||
from app.flow.nodes.delay import DelayNode
|
||||
from app.flow.nodes.exec import ExecNode
|
||||
from app.flow.nodes.file import FileNode
|
||||
from app.flow.nodes.http import HttpNode
|
||||
from app.flow.nodes.influx import InfluxDbNode
|
||||
from app.flow.nodes.inject import InjectNode
|
||||
from app.flow.nodes.logic import ChangeNode, JoinNode, RbeNode, SwitchNode
|
||||
from app.flow.nodes.mlp import MLPNode
|
||||
from app.flow.nodes.mqtt import MqttNode
|
||||
from app.flow.nodes.ntfy import NtfyNode
|
||||
from app.flow.nodes.trigger import TriggerNode
|
||||
|
||||
__all__ = [
|
||||
"ChangeNode",
|
||||
"DelayNode",
|
||||
"ExecNode",
|
||||
"FileNode",
|
||||
"HttpNode",
|
||||
"InfluxDbNode",
|
||||
"InjectNode",
|
||||
"JoinNode",
|
||||
"MLPNode",
|
||||
"MqttNode",
|
||||
"Node",
|
||||
"NtfyNode",
|
||||
"RESERVED_SETTINGS",
|
||||
"RbeNode",
|
||||
"SwitchNode",
|
||||
"TriggerNode",
|
||||
]
|
||||
@@ -18,8 +18,8 @@ fileConfig(config.config_file_name)
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
# target_metadata = None
|
||||
|
||||
from app.models import SQLModel # noqa
|
||||
from app.core.config import settings # noqa
|
||||
from fluksio.models import SQLModel # noqa
|
||||
from fluksio.core.config import settings # noqa
|
||||
|
||||
target_metadata = SQLModel.metadata
|
||||
|
||||
@@ -8,15 +8,15 @@ from jwt.exceptions import InvalidTokenError
|
||||
from pydantic import ValidationError
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from app.cloud import config as cloud_config
|
||||
from app.core import security
|
||||
from app.core.config import settings
|
||||
from app.core.db import engine
|
||||
from app.flow import panels
|
||||
from app.flow.controller import FlowController
|
||||
from app.flow.dashboards import DashboardStore
|
||||
from app.flow.workers import PythonWorkerPool
|
||||
from app.models import TokenPayload, User
|
||||
from fluksio.cloud import config as cloud_config
|
||||
from fluksio.core import security
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.core.db import engine
|
||||
from fluksio.flow import panels
|
||||
from fluksio.flow.controller import FlowController
|
||||
from fluksio.flow.dashboards import DashboardStore
|
||||
from fluksio.flow.workers import PythonWorkerPool
|
||||
from fluksio.models import TokenPayload, User
|
||||
|
||||
reusable_oauth2 = OAuth2PasswordBearer(
|
||||
tokenUrl=f"{settings.API_V1_STR}/login/access-token"
|
||||
@@ -1,6 +1,6 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.api.routes import (
|
||||
from fluksio.api.routes import (
|
||||
alerts,
|
||||
artifacts,
|
||||
cloud,
|
||||
@@ -6,10 +6,10 @@ from typing import Any
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
from app.api.deps import FlowControllerDep, get_current_user
|
||||
from app.core.config import settings
|
||||
from app.flow.alerts import Alert, AlertsConfig
|
||||
from app.models import Message
|
||||
from fluksio.api.deps import FlowControllerDep, get_current_user
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.flow.alerts import Alert, AlertsConfig
|
||||
from fluksio.models import Message
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/alerts", tags=["alerts"], dependencies=[Depends(get_current_user)]
|
||||
@@ -13,10 +13,10 @@ from jwt.exceptions import InvalidTokenError
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.api.deps import user_from_token
|
||||
from app.core import security
|
||||
from app.core.db import engine
|
||||
from app.flow.artifacts import ArtifactStore
|
||||
from fluksio.api.deps import user_from_token
|
||||
from fluksio.core import security
|
||||
from fluksio.core.db import engine
|
||||
from fluksio.flow.artifacts import ArtifactStore
|
||||
|
||||
|
||||
def artifact_caller(request: Request) -> str:
|
||||
@@ -23,16 +23,16 @@ from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlmodel import select
|
||||
|
||||
from app import crud
|
||||
from app.api.deps import (
|
||||
from fluksio import crud
|
||||
from fluksio.api.deps import (
|
||||
CurrentUser,
|
||||
SessionDep,
|
||||
get_current_active_superuser,
|
||||
get_current_user,
|
||||
)
|
||||
from app.cloud import config as cloud_config
|
||||
from app.core.security import get_password_hash
|
||||
from app.models import Message, User, UserPublic
|
||||
from fluksio.cloud import config as cloud_config
|
||||
from fluksio.core.security import get_password_hash
|
||||
from fluksio.models import Message, User, UserPublic
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -279,7 +279,7 @@ def disconnect(request: Request) -> Message:
|
||||
|
||||
|
||||
def _start_connector(app: Any) -> None:
|
||||
from app.cloud.connector import CloudConnector
|
||||
from fluksio.cloud.connector import CloudConnector
|
||||
|
||||
existing = getattr(app.state, "cloud_task", None)
|
||||
if existing is not None:
|
||||
@@ -7,17 +7,17 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.api.deps import DashboardStoreDep, FlowControllerDep, get_current_user
|
||||
from app.flow.dashboards import (
|
||||
from fluksio.api.deps import DashboardStoreDep, FlowControllerDep, get_current_user
|
||||
from fluksio.flow.dashboards import (
|
||||
DashboardDef,
|
||||
DashboardExists,
|
||||
DashboardNotFound,
|
||||
DashboardsPublic,
|
||||
default_dashboard,
|
||||
)
|
||||
from app.flow.events import event_bus
|
||||
from app.flow.store import StaleVersion
|
||||
from app.models import Message
|
||||
from fluksio.flow.events import event_bus
|
||||
from fluksio.flow.store import StaleVersion
|
||||
from fluksio.models import Message
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/dashboards", tags=["dashboards"], dependencies=[Depends(get_current_user)]
|
||||
@@ -18,7 +18,7 @@ from pydantic import BaseModel
|
||||
from sqlalchemy import delete
|
||||
from sqlmodel import Session, col, select
|
||||
|
||||
from app.api.deps import (
|
||||
from fluksio.api.deps import (
|
||||
CurrentUser,
|
||||
FlowControllerDep,
|
||||
SessionDep,
|
||||
@@ -26,15 +26,15 @@ from app.api.deps import (
|
||||
get_current_user,
|
||||
user_from_token,
|
||||
)
|
||||
from app.core.db import engine
|
||||
from app.flow.controller import FlowController
|
||||
from app.flow.dashboards import DashboardStore
|
||||
from app.flow.events import event_bus
|
||||
from app.flow.messages import qualify
|
||||
from app.flow.panels import messages_for
|
||||
from app.flow.pipeline import ValidationIssue
|
||||
from app.flow.runs import RunRejected
|
||||
from app.flow.schemas import (
|
||||
from fluksio.core.db import engine
|
||||
from fluksio.flow.controller import FlowController
|
||||
from fluksio.flow.dashboards import DashboardStore
|
||||
from fluksio.flow.events import event_bus
|
||||
from fluksio.flow.messages import qualify
|
||||
from fluksio.flow.panels import messages_for
|
||||
from fluksio.flow.pipeline import ValidationIssue
|
||||
from fluksio.flow.runs import RunRejected
|
||||
from fluksio.flow.schemas import (
|
||||
NAME_PATTERN,
|
||||
BrainGraph,
|
||||
FlowDef,
|
||||
@@ -49,15 +49,15 @@ from app.flow.schemas import (
|
||||
NodeStatusPublic,
|
||||
NodeTypeInfo,
|
||||
)
|
||||
from app.flow.state import as_number
|
||||
from app.flow.store import (
|
||||
from fluksio.flow.state import as_number
|
||||
from fluksio.flow.store import (
|
||||
FlowExists,
|
||||
FlowNotFound,
|
||||
LibExists,
|
||||
LibNotFound,
|
||||
StaleVersion,
|
||||
)
|
||||
from app.models import Message, Run, RunArtifact, RunMetric, RunNode
|
||||
from fluksio.models import Message, Run, RunArtifact, RunMetric, RunNode
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/flows", tags=["flows"], dependencies=[Depends(get_current_user)]
|
||||
@@ -287,7 +287,7 @@ def read_flows(controller: FlowControllerDep) -> Any:
|
||||
@router.get("/node-types", response_model=list[NodeTypeInfo])
|
||||
def read_node_types() -> Any:
|
||||
"""The node types that can be placed on a canvas."""
|
||||
from app.flow.controller import node_type_info
|
||||
from fluksio.flow.controller import node_type_info
|
||||
|
||||
return node_type_info()
|
||||
|
||||
@@ -5,12 +5,12 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
from app import crud
|
||||
from app.api.deps import CurrentUser, SessionDep, get_current_active_superuser
|
||||
from app.core import security
|
||||
from app.core.config import settings
|
||||
from app.models import Message, NewPassword, Token, UserPublic, UserUpdate
|
||||
from app.utils import (
|
||||
from fluksio import crud
|
||||
from fluksio.api.deps import CurrentUser, SessionDep, get_current_active_superuser
|
||||
from fluksio.core import security
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.models import Message, NewPassword, Token, UserPublic, UserUpdate
|
||||
from fluksio.utils import (
|
||||
generate_password_reset_token,
|
||||
generate_reset_password_email,
|
||||
send_email,
|
||||
@@ -12,10 +12,10 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.api.deps import FlowControllerDep, get_current_user
|
||||
from app.flow.messages import flow_of
|
||||
from app.flow.pipeline import ValueSource
|
||||
from app.flow.state import as_number
|
||||
from fluksio.api.deps import FlowControllerDep, get_current_user
|
||||
from fluksio.flow.messages import flow_of
|
||||
from fluksio.flow.pipeline import ValueSource
|
||||
from fluksio.flow.state import as_number
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/messages", tags=["messages"], dependencies=[Depends(get_current_user)]
|
||||
@@ -12,15 +12,15 @@ from typing import Any
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
from app.api.deps import (
|
||||
from fluksio.api.deps import (
|
||||
CurrentUser,
|
||||
FlowControllerDep,
|
||||
WorkerPoolDep,
|
||||
get_current_user,
|
||||
)
|
||||
from app.flow import modules
|
||||
from app.flow.events import event_bus
|
||||
from app.flow.schemas import ApplyRequest, ApplyResult, ModulesInfo
|
||||
from fluksio.flow import modules
|
||||
from fluksio.flow.events import event_bus
|
||||
from fluksio.flow.schemas import ApplyRequest, ApplyResult, ModulesInfo
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/modules", tags=["modules"], dependencies=[Depends(get_current_user)]
|
||||
@@ -36,15 +36,15 @@ from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import col, select
|
||||
|
||||
from app.api.deps import (
|
||||
from fluksio.api.deps import (
|
||||
CurrentUser,
|
||||
SessionDep,
|
||||
get_current_active_superuser,
|
||||
get_current_user,
|
||||
)
|
||||
from app.core import security
|
||||
from app.core.config import settings
|
||||
from app.models import (
|
||||
from fluksio.core import security
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.models import (
|
||||
Message,
|
||||
OAuthAuthorizationCode,
|
||||
OAuthAuthorizeInfo,
|
||||
+4
-4
@@ -17,10 +17,10 @@ from sqlalchemy import ColumnElement, DateTime, Interval, cast, func, literal
|
||||
from sqlalchemy import select as sa_select
|
||||
from sqlmodel import col, select
|
||||
|
||||
from app.api.deps import FlowControllerDep, SessionDep, get_current_user
|
||||
from app.core.config import settings
|
||||
from app.flow.controller import ADVISORY_ISSUES, NodeStatus
|
||||
from app.models import EngineEvent, FlowRun, MetricBucket
|
||||
from fluksio.api.deps import FlowControllerDep, SessionDep, get_current_user
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.flow.controller import ADVISORY_ISSUES, NodeStatus
|
||||
from fluksio.models import EngineEvent, FlowRun, MetricBucket
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/observability",
|
||||
@@ -11,7 +11,7 @@ without a session — a device with no credential is the whole point of them —
|
||||
and mints the credential itself when the approval comes. Which side minted it
|
||||
changes nothing about what it may do: the scope check is here either way.
|
||||
|
||||
The credential is scoped: ``app.api.deps`` lets it reach the dashboards that
|
||||
The credential is scoped: ``fluksio.api.deps`` lets it reach the dashboards that
|
||||
panel was assigned and nothing else. Removing the panel revokes it.
|
||||
"""
|
||||
|
||||
@@ -27,13 +27,13 @@ from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.api.deps import CurrentUser, get_current_active_superuser, get_current_user
|
||||
from app.cloud import config as cloud_config
|
||||
from app.core import security
|
||||
from app.core.config import settings
|
||||
from app.flow.events import event_bus
|
||||
from app.flow.panels import PanelDef, PanelsConfig, find, read_config, write_config
|
||||
from app.models import Message
|
||||
from fluksio.api.deps import CurrentUser, get_current_active_superuser, get_current_user
|
||||
from fluksio.cloud import config as cloud_config
|
||||
from fluksio.core import security
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.flow.events import event_bus
|
||||
from fluksio.flow.panels import PanelDef, PanelsConfig, find, read_config, write_config
|
||||
from fluksio.models import Message
|
||||
|
||||
#: Gated per route rather than on the router: the two pairing endpoints are the
|
||||
#: only unauthenticated ones in the app, because a device with no credential is
|
||||
@@ -3,10 +3,10 @@ from typing import Any
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.api.deps import SessionDep
|
||||
from app.core.config import settings
|
||||
from app.core.security import get_password_hash
|
||||
from app.models import (
|
||||
from fluksio.api.deps import SessionDep
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.core.security import get_password_hash
|
||||
from fluksio.models import (
|
||||
User,
|
||||
UserPublic,
|
||||
)
|
||||
@@ -12,10 +12,10 @@ from fastapi.concurrency import run_in_threadpool
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlmodel import col, select
|
||||
|
||||
from app.api.deps import CurrentUser, SessionDep, get_current_user
|
||||
from app.flow.runs import RunRejected, RunService, new_run_id
|
||||
from app.flow.store import FlowNotFound
|
||||
from app.models import Run, RunArtifact, RunMetric, RunNode
|
||||
from fluksio.api.deps import CurrentUser, SessionDep, get_current_user
|
||||
from fluksio.flow.runs import RunRejected, RunService, new_run_id
|
||||
from fluksio.flow.store import FlowNotFound
|
||||
from fluksio.models import Run, RunArtifact, RunMetric, RunNode
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/runs", tags=["runs"], dependencies=[Depends(get_current_user)]
|
||||
@@ -9,9 +9,9 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.api.deps import get_current_user
|
||||
from app.flow.secrets import SecretNotFound, get_secrets
|
||||
from app.models import Message
|
||||
from fluksio.api.deps import get_current_user
|
||||
from fluksio.flow.secrets import SecretNotFound, get_secrets
|
||||
from fluksio.models import Message
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/secrets", tags=["secrets"], dependencies=[Depends(get_current_user)]
|
||||
@@ -4,16 +4,16 @@ from typing import Any
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlmodel import col, func, select
|
||||
|
||||
from app import crud
|
||||
from app.api.deps import (
|
||||
from fluksio import crud
|
||||
from fluksio.api.deps import (
|
||||
CurrentUser,
|
||||
SessionDep,
|
||||
get_current_active_superuser,
|
||||
)
|
||||
from app.api.routes.cloud import forget_remote_user
|
||||
from app.core.config import settings
|
||||
from app.core.security import get_password_hash, verify_password
|
||||
from app.models import (
|
||||
from fluksio.api.routes.cloud import forget_remote_user
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.core.security import get_password_hash, verify_password
|
||||
from fluksio.models import (
|
||||
Message,
|
||||
UpdatePassword,
|
||||
User,
|
||||
@@ -24,7 +24,7 @@ from app.models import (
|
||||
UserUpdate,
|
||||
UserUpdateMe,
|
||||
)
|
||||
from app.utils import generate_new_account_email, send_email
|
||||
from fluksio.utils import generate_new_account_email, send_email
|
||||
|
||||
router = APIRouter(prefix="/users", tags=["users"])
|
||||
|
||||
@@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Request, Response
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from pydantic.networks import EmailStr
|
||||
|
||||
from app.api.deps import get_current_active_superuser
|
||||
from app.flow.state import RedisState
|
||||
from app.models import Message
|
||||
from app.utils import generate_test_email, send_email
|
||||
from fluksio.api.deps import get_current_active_superuser
|
||||
from fluksio.flow.state import RedisState
|
||||
from fluksio.models import Message
|
||||
from fluksio.utils import generate_test_email, send_email
|
||||
|
||||
router = APIRouter(prefix="/utils", tags=["utils"])
|
||||
|
||||
@@ -18,10 +18,10 @@ from fastapi.responses import PlainTextResponse
|
||||
from jwt.exceptions import InvalidTokenError
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.api.deps import get_current_active_superuser, get_current_user
|
||||
from app.core import security
|
||||
from app.flow import worker_main
|
||||
from app.flow.remote import PROTOCOL, RemoteWorker, RemoteWorkerHub
|
||||
from fluksio.api.deps import get_current_active_superuser, get_current_user
|
||||
from fluksio.core import security
|
||||
from fluksio.flow import worker_main
|
||||
from fluksio.flow.remote import PROTOCOL, RemoteWorker, RemoteWorkerHub
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -4,7 +4,7 @@ from sqlalchemy import Engine
|
||||
from sqlmodel import Session, select
|
||||
from tenacity import after_log, before_log, retry, stop_after_attempt, wait_fixed
|
||||
|
||||
from app.core.db import engine
|
||||
from fluksio.core.db import engine
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -24,7 +24,7 @@ from typing import Any
|
||||
import jwt
|
||||
from jwt.exceptions import InvalidTokenError
|
||||
|
||||
from app.core.config import settings
|
||||
from fluksio.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -26,8 +26,8 @@ from typing import Any
|
||||
import httpx
|
||||
from fastapi import FastAPI
|
||||
|
||||
from app.cloud import config as cloud_config
|
||||
from app.core.config import settings
|
||||
from fluksio.cloud import config as cloud_config
|
||||
from fluksio.core.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -158,8 +158,8 @@ class CloudConnector:
|
||||
"""
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from app.core.db import engine
|
||||
from app.models import User
|
||||
from fluksio.core.db import engine
|
||||
from fluksio.models import User
|
||||
|
||||
if not owner:
|
||||
return
|
||||
@@ -208,7 +208,7 @@ class CloudConnector:
|
||||
a short-lived local token: the observability API is authenticated, and
|
||||
this process is entitled to mint one for the enrolling user.
|
||||
"""
|
||||
from app.core import security
|
||||
from fluksio.core import security
|
||||
|
||||
token = security.create_access_token(config.local_user_id, timedelta(minutes=5))
|
||||
try:
|
||||
@@ -339,14 +339,14 @@ class CloudConnector:
|
||||
"""
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.api.deps import user_from_token
|
||||
from app.api.routes.flows import (
|
||||
from fluksio.api.deps import user_from_token
|
||||
from fluksio.api.routes.flows import (
|
||||
event_for_panel,
|
||||
panel_scope,
|
||||
snapshot_payload,
|
||||
)
|
||||
from app.core.db import engine
|
||||
from app.flow.events import event_bus
|
||||
from fluksio.core.db import engine
|
||||
from fluksio.flow.events import event_bus
|
||||
|
||||
stream_id = str(frame["id"])
|
||||
path = str(frame.get("path") or "")
|
||||
@@ -1,8 +1,8 @@
|
||||
from sqlmodel import Session, create_engine, select
|
||||
|
||||
from app import crud
|
||||
from app.core.config import settings
|
||||
from app.models import User, UserCreate
|
||||
from fluksio import crud
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.models import User, UserCreate
|
||||
|
||||
# A connection idle across a Postgres restart is dead but still pooled; the
|
||||
# pre-ping spends a round trip to find out instead of failing the request.
|
||||
@@ -11,7 +11,7 @@ from pwdlib import PasswordHash
|
||||
from pwdlib.hashers.argon2 import Argon2Hasher
|
||||
from pwdlib.hashers.bcrypt import BcryptHasher
|
||||
|
||||
from app.core.config import settings
|
||||
from fluksio.core.config import settings
|
||||
|
||||
password_hash = PasswordHash(
|
||||
(
|
||||
@@ -182,7 +182,7 @@ def create_panel_token(
|
||||
person in exactly the same way: ``sub`` is the account that approved the
|
||||
pairing, so everything the panel does is attributable to them. What keeps
|
||||
it from being a full session is the ``panel`` claim — the request filter in
|
||||
``app.api.deps`` lets it reach only that panel's dashboards and the message
|
||||
``fluksio.api.deps`` lets it reach only that panel's dashboards and the message
|
||||
endpoints its widgets need.
|
||||
|
||||
Long-lived on purpose: a wall tablet is set up once and left running, and
|
||||
@@ -2,8 +2,8 @@ from typing import Any
|
||||
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from app.core.security import get_password_hash, verify_password
|
||||
from app.models import User, UserCreate, UserUpdate
|
||||
from fluksio.core.security import get_password_hash, verify_password
|
||||
from fluksio.models import User, UserCreate, UserUpdate
|
||||
|
||||
|
||||
def create_user(*, session: Session, user_create: UserCreate) -> User:
|
||||
@@ -0,0 +1,26 @@
|
||||
"""The flow engine: nodes, the pipeline that runs them, and their storage."""
|
||||
|
||||
from fluksio.flow.controller import FlowController, NodeStatus
|
||||
from fluksio.flow.events import EventBus, event_bus
|
||||
from fluksio.flow.messages import DType, MessageSpec, qualify
|
||||
from fluksio.flow.nodes import Node
|
||||
from fluksio.flow.pipeline import Pipeline, ValidationIssue
|
||||
from fluksio.flow.state import MemoryState, RedisState, StateBackend
|
||||
from fluksio.flow.store import FlowStore
|
||||
|
||||
__all__ = [
|
||||
"DType",
|
||||
"EventBus",
|
||||
"FlowController",
|
||||
"FlowStore",
|
||||
"MemoryState",
|
||||
"MessageSpec",
|
||||
"Node",
|
||||
"NodeStatus",
|
||||
"Pipeline",
|
||||
"RedisState",
|
||||
"StateBackend",
|
||||
"ValidationIssue",
|
||||
"event_bus",
|
||||
"qualify",
|
||||
]
|
||||
@@ -22,8 +22,8 @@ from typing import Any, Literal
|
||||
import httpx
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.flow.events import EventBus
|
||||
from app.flow.secrets import resolve_params
|
||||
from fluksio.flow.events import EventBus
|
||||
from fluksio.flow.secrets import resolve_params
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -351,8 +351,8 @@ class AlertManager:
|
||||
response.raise_for_status()
|
||||
|
||||
async def _send_email(self, config: dict[str, Any], alert: Alert) -> None:
|
||||
from app.core.config import settings
|
||||
from app.utils import send_email
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.utils import send_email
|
||||
|
||||
recipient = config.get("to")
|
||||
if not recipient:
|
||||
@@ -32,7 +32,7 @@ from typing import TYPE_CHECKING, Any, ClassVar
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.flow.nodes import Node
|
||||
from fluksio.flow.nodes import Node
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import FastAPI
|
||||
@@ -21,12 +21,12 @@ from typing import Any, cast
|
||||
from fastapi import FastAPI
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
from app.core.config import settings
|
||||
from app.flow.alerts import AlertManager
|
||||
from app.flow.events import EventBus
|
||||
from app.flow.executor import ExecutionService
|
||||
from app.flow.messages import MessageSpec, flow_of, qualify
|
||||
from app.flow.nodes import (
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.flow.alerts import AlertManager
|
||||
from fluksio.flow.events import EventBus
|
||||
from fluksio.flow.executor import ExecutionService
|
||||
from fluksio.flow.messages import MessageSpec, flow_of, qualify
|
||||
from fluksio.flow.nodes import (
|
||||
RESERVED_SETTINGS,
|
||||
ChangeNode,
|
||||
DelayNode,
|
||||
@@ -44,9 +44,9 @@ from app.flow.nodes import (
|
||||
SwitchNode,
|
||||
TriggerNode,
|
||||
)
|
||||
from app.flow.pipeline import NodeOutcome, Pipeline, ValidationIssue, ValueSource
|
||||
from app.flow.remote import RemoteWorkerHub
|
||||
from app.flow.schemas import (
|
||||
from fluksio.flow.pipeline import NodeOutcome, Pipeline, ValidationIssue, ValueSource
|
||||
from fluksio.flow.remote import RemoteWorkerHub
|
||||
from fluksio.flow.schemas import (
|
||||
BrainEdge,
|
||||
BrainGraph,
|
||||
BrainNode,
|
||||
@@ -56,12 +56,12 @@ from app.flow.schemas import (
|
||||
NodeStatusPublic,
|
||||
NodeTypeInfo,
|
||||
)
|
||||
from app.flow.secrets import SecretNotFound, resolve_params
|
||||
from app.flow.state import MemoryState, StateBackend
|
||||
from app.flow.store import LIB_DIR, FlowNotFound, FlowStore, LibNotFound
|
||||
from app.flow.supervision import Supervisor
|
||||
from app.flow.worker_main import load_function
|
||||
from app.flow.workers import PythonWorkerPool
|
||||
from fluksio.flow.secrets import SecretNotFound, resolve_params
|
||||
from fluksio.flow.state import MemoryState, StateBackend
|
||||
from fluksio.flow.store import LIB_DIR, FlowNotFound, FlowStore, LibNotFound
|
||||
from fluksio.flow.supervision import Supervisor
|
||||
from fluksio.flow.worker_main import load_function
|
||||
from fluksio.flow.workers import PythonWorkerPool
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -807,7 +807,7 @@ class FlowController:
|
||||
What a dashboard picks from, so it spans flows rather than sitting
|
||||
inside one.
|
||||
"""
|
||||
from app.api.routes.messages import MessageInfo
|
||||
from fluksio.api.routes.messages import MessageInfo
|
||||
|
||||
specs: dict[str, MessageSpec] = {}
|
||||
providers: dict[str, list[str]] = {}
|
||||
@@ -23,8 +23,8 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator, model_validator
|
||||
|
||||
from app.flow.schemas import _validate_name
|
||||
from app.flow.store import FlowStore, StaleVersion
|
||||
from fluksio.flow.schemas import _validate_name
|
||||
from fluksio.flow.store import FlowStore, StaleVersion
|
||||
|
||||
#: Sibling of the shared-node library, and likewise not a flow.
|
||||
DASHBOARD_DIR = "_dashboards"
|
||||
@@ -18,11 +18,11 @@ import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from app.flow.queue import MAX_DELIVERIES, WorkItem, WorkQueue
|
||||
from fluksio.flow.queue import MAX_DELIVERIES, WorkItem, WorkQueue
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.flow.events import EventBus
|
||||
from app.flow.pipeline import Pipeline
|
||||
from fluksio.flow.events import EventBus
|
||||
from fluksio.flow.pipeline import Pipeline
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -22,10 +22,10 @@ from sqlalchemy import delete, func, update
|
||||
from sqlalchemy.dialects.postgresql import insert
|
||||
from sqlmodel import Session, col
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.db import engine
|
||||
from app.flow.events import EventBus
|
||||
from app.models import EngineEvent, FlowRun, MetricBucket
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.core.db import engine
|
||||
from fluksio.flow.events import EventBus
|
||||
from fluksio.models import EngineEvent, FlowRun, MetricBucket
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -22,11 +22,11 @@ import tempfile
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from app.core.config import settings
|
||||
from app.flow.schemas import ModulePackage, ModulesInfo
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.flow.schemas import ModulePackage, ModulesInfo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.flow.store import FlowStore
|
||||
from fluksio.flow.store import FlowStore
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
"""Built-in node types.
|
||||
|
||||
Split by the outside world each one talks to. Importing from
|
||||
``fluksio.flow.nodes`` keeps working, which is what every caller does.
|
||||
"""
|
||||
|
||||
from fluksio.flow.nodes.base import RESERVED_SETTINGS, Node
|
||||
from fluksio.flow.nodes.delay import DelayNode
|
||||
from fluksio.flow.nodes.exec import ExecNode
|
||||
from fluksio.flow.nodes.file import FileNode
|
||||
from fluksio.flow.nodes.http import HttpNode
|
||||
from fluksio.flow.nodes.influx import InfluxDbNode
|
||||
from fluksio.flow.nodes.inject import InjectNode
|
||||
from fluksio.flow.nodes.logic import ChangeNode, JoinNode, RbeNode, SwitchNode
|
||||
from fluksio.flow.nodes.mlp import MLPNode
|
||||
from fluksio.flow.nodes.mqtt import MqttNode
|
||||
from fluksio.flow.nodes.ntfy import NtfyNode
|
||||
from fluksio.flow.nodes.trigger import TriggerNode
|
||||
|
||||
__all__ = [
|
||||
"ChangeNode",
|
||||
"DelayNode",
|
||||
"ExecNode",
|
||||
"FileNode",
|
||||
"HttpNode",
|
||||
"InfluxDbNode",
|
||||
"InjectNode",
|
||||
"JoinNode",
|
||||
"MLPNode",
|
||||
"MqttNode",
|
||||
"Node",
|
||||
"NtfyNode",
|
||||
"RESERVED_SETTINGS",
|
||||
"RbeNode",
|
||||
"SwitchNode",
|
||||
"TriggerNode",
|
||||
]
|
||||
@@ -12,15 +12,15 @@ import logging
|
||||
from collections.abc import Callable, Coroutine, Iterable, Iterator
|
||||
from typing import TYPE_CHECKING, Any, TypeAlias
|
||||
|
||||
from app.flow import logs
|
||||
from app.flow.messages import MessageSpec, qualify
|
||||
from app.flow.supervision import Supervisor
|
||||
from fluksio.flow import logs
|
||||
from fluksio.flow.messages import MessageSpec, qualify
|
||||
from fluksio.flow.supervision import Supervisor
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import FastAPI
|
||||
|
||||
from app.flow.pipeline import Pipeline
|
||||
from app.flow.state import StateBackend
|
||||
from fluksio.flow.pipeline import Pipeline
|
||||
from fluksio.flow.state import StateBackend
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import FastAPI
|
||||
@@ -15,8 +15,8 @@ from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -14,15 +14,15 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def files_root() -> Path:
|
||||
"""Where flow-readable files live: beside the flow store, not inside it."""
|
||||
from app.core.config import settings
|
||||
from fluksio.core.config import settings
|
||||
|
||||
return settings.FLOWS_DIR.parent / "files"
|
||||
|
||||
@@ -13,8 +13,8 @@ from urllib.parse import urlsplit, urlunsplit
|
||||
import httpx
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import FastAPI
|
||||
@@ -8,8 +8,8 @@ from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node, NodeResult
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node, NodeResult
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -15,8 +15,8 @@ from typing import TYPE_CHECKING, Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import FastAPI
|
||||
@@ -14,8 +14,8 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -10,8 +10,8 @@ from typing import Any
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -11,8 +11,8 @@ from typing import TYPE_CHECKING, Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import FastAPI
|
||||
@@ -13,9 +13,9 @@ from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from app.flow.nodes.http import shared_client
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
from fluksio.flow.nodes.http import shared_client
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -13,8 +13,8 @@ from typing import Any
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from app.flow.nodes.base import Node
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
from fluksio.flow.nodes.base import Node
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -16,9 +16,9 @@ from pathlib import Path
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from app.core.config import settings
|
||||
from app.flow.dashboards import DashboardNotFound, DashboardStore
|
||||
from app.flow.schemas import _validate_name
|
||||
from fluksio.core.config import settings
|
||||
from fluksio.flow.dashboards import DashboardNotFound, DashboardStore
|
||||
from fluksio.flow.schemas import _validate_name
|
||||
|
||||
|
||||
class PanelDef(BaseModel):
|
||||
@@ -20,13 +20,13 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.flow import logs
|
||||
from app.flow.artifacts import is_reference
|
||||
from app.flow.events import EventBus
|
||||
from app.flow.messages import flow_of
|
||||
from app.flow.nodes import Node
|
||||
from app.flow.queue import WorkQueue
|
||||
from app.flow.state import MemoryState, StateBackend
|
||||
from fluksio.flow import logs
|
||||
from fluksio.flow.artifacts import is_reference
|
||||
from fluksio.flow.events import EventBus
|
||||
from fluksio.flow.messages import flow_of
|
||||
from fluksio.flow.nodes import Node
|
||||
from fluksio.flow.queue import WorkQueue
|
||||
from fluksio.flow.state import MemoryState, StateBackend
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -1136,7 +1136,7 @@ class Pipeline:
|
||||
Returns False when there is no queue to hold the item, in which case
|
||||
the caller has to wait however it waited before.
|
||||
"""
|
||||
from app.flow.queue import WorkItem
|
||||
from fluksio.flow.queue import WorkItem
|
||||
|
||||
if self._queue is None or seconds <= 0:
|
||||
return False
|
||||
@@ -1158,7 +1158,7 @@ class Pipeline:
|
||||
|
||||
def _enqueue_cascade(self, node: Node, outputs: dict[str, Any] | None) -> None:
|
||||
"""Journal a trigger, or fall back to running it here if that fails."""
|
||||
from app.flow.queue import WorkItem
|
||||
from fluksio.flow.queue import WorkItem
|
||||
|
||||
item = WorkItem(
|
||||
kind="cascade",
|
||||
@@ -15,7 +15,7 @@ from __future__ import annotations
|
||||
import logging
|
||||
from importlib.metadata import entry_points
|
||||
|
||||
from app.flow.connector import CONTRACT_VERSION, ConnectorNode
|
||||
from fluksio.flow.connector import CONTRACT_VERSION, ConnectorNode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -24,7 +24,7 @@ ENTRY_POINT_GROUP = "fluksio.node_types"
|
||||
|
||||
def load_plugins() -> list[str]:
|
||||
"""Register every installed connector. Returns the type names it added."""
|
||||
from app.flow.controller import NODE_TYPES, NodeType, _schema_of
|
||||
from fluksio.flow.controller import NODE_TYPES, NodeType, _schema_of
|
||||
|
||||
added: list[str] = []
|
||||
for entry in entry_points(group=ENTRY_POINT_GROUP):
|
||||
@@ -30,7 +30,7 @@ import time
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
from app.flow.workers import NodeTimeout, RemoteError, _remote_class
|
||||
from fluksio.flow.workers import NodeTimeout, RemoteError, _remote_class
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -42,14 +42,14 @@ from sqlalchemy import update
|
||||
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||
from sqlmodel import Session, col, select
|
||||
|
||||
from app.core.db import engine as db_engine
|
||||
from app.flow.controller import FlowController, RunContext
|
||||
from app.flow.messages import qualify
|
||||
from app.flow.pipeline import NodeOutcome, Pipeline
|
||||
from app.flow.queue import WorkItem, WorkQueue
|
||||
from app.flow.schemas import FlowDef
|
||||
from app.flow.state import MemoryState, StateBackend
|
||||
from app.models import Run, RunArtifact, RunMetric, RunNode
|
||||
from fluksio.core.db import engine as db_engine
|
||||
from fluksio.flow.controller import FlowController, RunContext
|
||||
from fluksio.flow.messages import qualify
|
||||
from fluksio.flow.pipeline import NodeOutcome, Pipeline
|
||||
from fluksio.flow.queue import WorkItem, WorkQueue
|
||||
from fluksio.flow.schemas import FlowDef
|
||||
from fluksio.flow.state import MemoryState, StateBackend
|
||||
from fluksio.models import Run, RunArtifact, RunMetric, RunNode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -11,7 +11,7 @@ from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
from app.flow.messages import MessageSpec
|
||||
from fluksio.flow.messages import MessageSpec
|
||||
|
||||
NAME_PATTERN = re.compile(r"^[a-z][a-z0-9_]*$")
|
||||
|
||||
@@ -21,7 +21,7 @@ import subprocess
|
||||
import threading
|
||||
from pathlib import Path
|
||||
|
||||
from app.flow.schemas import FlowDef
|
||||
from fluksio.flow.schemas import FlowDef
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -20,7 +20,7 @@ from collections import deque
|
||||
from collections.abc import Callable, Coroutine
|
||||
from typing import Any
|
||||
|
||||
from app.flow.events import EventBus
|
||||
from fluksio.flow.events import EventBus
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -15,7 +15,7 @@ import os
|
||||
import time
|
||||
from collections import deque
|
||||
|
||||
from app.flow.events import EventBus
|
||||
from fluksio.flow.events import EventBus
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -131,7 +131,7 @@ def _store_bytes(data: bytes, name: str, media_type: str) -> dict[str, Any]:
|
||||
A worker in the engine's own container writes the file; one on another host
|
||||
puts it over HTTP. Node code cannot tell the difference, which is the point
|
||||
— the same flow runs either place. The hashing is repeated from
|
||||
``app.flow.artifacts`` rather than imported, because nothing of the app is
|
||||
``fluksio.flow.artifacts`` rather than imported, because nothing of the app is
|
||||
importable here.
|
||||
"""
|
||||
digest = "sha256:" + hashlib.sha256(data).hexdigest()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user