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:
2026-08-21 21:48:05 +02:00
co-authored by Claude Opus 5
parent 97785ee590
commit 60d7ec81c0
170 changed files with 629 additions and 619 deletions
+2 -2
View File
@@ -5,8 +5,8 @@ from typing import Any
import pytest
from fastapi.testclient import TestClient
from app.core.config import settings
from app.flow.alerts import AlertsConfig, Channel
from fluksio.core.config import settings
from fluksio.flow.alerts import AlertsConfig, Channel
PREFIX = f"{settings.API_V1_STR}/alerts"
+2 -2
View File
@@ -4,8 +4,8 @@ from fastapi.testclient import TestClient
from sqlalchemy import func
from sqlmodel import Session, select
from app.core.config import settings
from app.models import Run, RunArtifact, RunMetric, RunNode
from fluksio.core.config import settings
from fluksio.models import Run, RunArtifact, RunMetric, RunNode
PREFIX = f"{settings.API_V1_STR}/flows"
+7 -7
View File
@@ -4,11 +4,11 @@ from fastapi.testclient import TestClient
from pwdlib.hashers.bcrypt import BcryptHasher
from sqlmodel import Session
from app.core.config import settings
from app.core.security import get_password_hash, verify_password
from app.crud import create_user
from app.models import User, UserCreate
from app.utils import generate_password_reset_token
from fluksio.core.config import settings
from fluksio.core.security import get_password_hash, verify_password
from fluksio.crud import create_user
from fluksio.models import User, UserCreate
from fluksio.utils import generate_password_reset_token
from tests.utils.user import user_authentication_headers
from tests.utils.utils import random_email, random_lower_string
@@ -50,8 +50,8 @@ def test_recovery_password(
client: TestClient, normal_user_token_headers: dict[str, str]
) -> None:
with (
patch("app.core.config.settings.SMTP_HOST", "smtp.example.com"),
patch("app.core.config.settings.SMTP_USER", "admin@example.com"),
patch("fluksio.core.config.settings.SMTP_HOST", "smtp.example.com"),
patch("fluksio.core.config.settings.SMTP_USER", "admin@example.com"),
):
email = "test@example.com"
r = client.post(
+1 -1
View File
@@ -8,7 +8,7 @@ from urllib.parse import parse_qs, urlparse
import pytest
from fastapi.testclient import TestClient
from app.core.config import settings
from fluksio.core.config import settings
PREFIX = f"{settings.API_V1_STR}/oauth"
REDIRECT = "http://127.0.0.1:41234/callback"
@@ -3,8 +3,8 @@ from datetime import datetime, timedelta, timezone
from fastapi.testclient import TestClient
from sqlmodel import Session
from app.core.config import settings
from app.models import EngineEvent, FlowRun, MetricBucket
from fluksio.core.config import settings
from fluksio.models import EngineEvent, FlowRun, MetricBucket
PREFIX = f"{settings.API_V1_STR}/observability"
FLOW = "observability-test"
@@ -90,7 +90,7 @@ def test_a_flow_that_cannot_run_makes_the_summary_degraded(
knows is what this reports — and reporting it is the whole point: a flow
with a dependency loop cannot run, and the screen used to say "ok".
"""
from app.flow.pipeline import ValidationIssue
from fluksio.flow.pipeline import ValidationIssue
controller = client.app.state.flow_controller
before = controller.issues
+4 -4
View File
@@ -2,8 +2,8 @@
from fastapi.testclient import TestClient
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
PREFIX = f"{settings.API_V1_STR}/panels"
DASHBOARDS = f"{settings.API_V1_STR}/dashboards"
@@ -276,7 +276,7 @@ def test_a_remote_device_is_paired_at_the_portal(
"""
import httpx
from app.api.routes import panels as panels_route
from fluksio.api.routes import panels as panels_route
calls: list[dict[str, object]] = []
@@ -378,7 +378,7 @@ def test_a_panels_socket_carries_only_what_it_draws(
applied to what goes out: no node status, no logs, no shape of the graph,
and no value belonging to a dashboard this panel does not show.
"""
from app.api.routes.flows import (
from fluksio.api.routes.flows import (
event_for_panel,
panel_scope,
snapshot_payload,
+2 -2
View File
@@ -2,8 +2,8 @@ import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, select
from app.core.config import settings
from app.models import User
from fluksio.core.config import settings
from fluksio.models import User
def test_create_user(client: TestClient, db: Session) -> None:
+2 -2
View File
@@ -10,8 +10,8 @@ from datetime import timedelta
from fastapi.testclient import TestClient
from app.core import security
from app.core.config import settings
from fluksio.core import security
from fluksio.core.config import settings
PROTECTED = [
f"{settings.API_V1_STR}/users/me",
+7 -7
View File
@@ -4,10 +4,10 @@ from unittest.mock import patch
from fastapi.testclient import TestClient
from sqlmodel import Session, select
from app import crud
from app.core.config import settings
from app.core.security import verify_password
from app.models import User, UserCreate
from fluksio import crud
from fluksio.core.config import settings
from fluksio.core.security import verify_password
from fluksio.models import User, UserCreate
from tests.utils.user import create_random_user
from tests.utils.utils import random_email, random_lower_string
@@ -38,9 +38,9 @@ def test_create_user_new_email(
client: TestClient, superuser_token_headers: dict[str, str], db: Session
) -> None:
with (
patch("app.utils.send_email", return_value=None),
patch("app.core.config.settings.SMTP_HOST", "smtp.example.com"),
patch("app.core.config.settings.SMTP_USER", "admin@example.com"),
patch("fluksio.utils.send_email", return_value=None),
patch("fluksio.core.config.settings.SMTP_HOST", "smtp.example.com"),
patch("fluksio.core.config.settings.SMTP_USER", "admin@example.com"),
):
username = random_email()
password = random_lower_string()
+5 -5
View File
@@ -10,11 +10,11 @@ from sqlalchemy import create_engine, text
from sqlalchemy.engine import make_url
from sqlmodel import Session, SQLModel, select
from app.cloud import config as cloud_config
from app.core.config import settings
from app.core.db import engine, init_db
from app.main import app
from app.models import User
from fluksio.cloud import config as cloud_config
from fluksio.core.config import settings
from fluksio.core.db import engine, init_db
from fluksio.main import app
from fluksio.models import User
from tests.utils.portal import INSTALLATION_ID, ISSUER, jwks
from tests.utils.user import authentication_token_from_email
from tests.utils.utils import get_superuser_token_headers
+3 -3
View File
@@ -2,9 +2,9 @@ from fastapi.encoders import jsonable_encoder
from pwdlib.hashers.bcrypt import BcryptHasher
from sqlmodel import Session
from app import crud
from app.core.security import verify_password
from app.models import User, UserCreate, UserUpdate
from fluksio import crud
from fluksio.core.security import verify_password
from fluksio.models import User, UserCreate, UserUpdate
from tests.utils.utils import random_email, random_lower_string
+2 -2
View File
@@ -6,7 +6,7 @@ from pathlib import Path
import pytest
from app.flow.alerts import (
from fluksio.flow.alerts import (
ALERTING_EVENTS,
FLAP_THRESHOLD,
RATE_LIMIT,
@@ -17,7 +17,7 @@ from app.flow.alerts import (
Rule,
describe,
)
from app.flow.events import EventBus
from fluksio.flow.events import EventBus
class Clock:
+6 -6
View File
@@ -9,12 +9,12 @@ from pathlib import Path
import pytest
from app.flow.controller import FlowController
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import MqttNode
from app.flow.pipeline import ValidationIssue
from app.flow.schemas import FlowDef, NodeDef
from app.flow.store import FlowStore
from fluksio.flow.controller import FlowController
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import MqttNode
from fluksio.flow.pipeline import ValidationIssue
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.store import FlowStore
BROKER = {"broker_host": "mosquitto", "broker_port": 1883, "topic": "sensors/temp"}
+9 -9
View File
@@ -3,12 +3,12 @@
import asyncio
from typing import Any
from app.flow.connector import CONTRACT_VERSION, ConnectorNode
from app.flow.controller import NODE_TYPES
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.plugins import load_plugins
from fluksio.flow.connector import CONTRACT_VERSION, ConnectorNode
from fluksio.flow.controller import NODE_TYPES
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.plugins import load_plugins
class Sensor(ConnectorNode):
@@ -146,7 +146,7 @@ def test_a_connector_is_discovered_from_its_entry_point(monkeypatch):
def load(self):
return Sensor
monkeypatch.setattr("app.flow.plugins.entry_points", lambda group: [FakeEntry()])
monkeypatch.setattr("fluksio.flow.plugins.entry_points", lambda group: [FakeEntry()])
try:
assert load_plugins() == ["test_sensor"]
assert NODE_TYPES["test_sensor"].plugin == "fluksio-connector-test 0.1.0"
@@ -166,7 +166,7 @@ def test_a_connector_written_for_another_contract_is_refused(monkeypatch):
def load(self):
return Outdated
monkeypatch.setattr("app.flow.plugins.entry_points", lambda group: [FakeEntry()])
monkeypatch.setattr("fluksio.flow.plugins.entry_points", lambda group: [FakeEntry()])
assert load_plugins() == []
assert "outdated" not in NODE_TYPES
@@ -179,6 +179,6 @@ def test_a_connector_may_not_take_over_a_built_in_type(monkeypatch):
def load(self): # pragma: no cover - never reached
raise AssertionError("should not be loaded")
monkeypatch.setattr("app.flow.plugins.entry_points", lambda group: [FakeEntry()])
monkeypatch.setattr("fluksio.flow.plugins.entry_points", lambda group: [FakeEntry()])
assert load_plugins() == []
assert NODE_TYPES["mqtt"].plugin is None
+6 -6
View File
@@ -2,7 +2,7 @@
import pytest
from app.flow.dashboards import (
from fluksio.flow.dashboards import (
DashboardDef,
DashboardNotFound,
DashboardStore,
@@ -11,11 +11,11 @@ from app.flow.dashboards import (
WidgetDef,
default_dashboard,
)
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.state import MemoryState
from app.flow.store import FlowStore, StaleVersion
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.state import MemoryState
from fluksio.flow.store import FlowStore, StaleVersion
@pytest.fixture
+5 -5
View File
@@ -2,11 +2,11 @@
import time
from app.flow.executor import ExecutionService
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.queue import MemoryWorkQueue
from fluksio.flow.executor import ExecutionService
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.queue import MemoryWorkQueue
# Short enough to wait out in a test, long enough not to race the engine.
WINDOW = 0.05
+3 -3
View File
@@ -4,9 +4,9 @@ from pathlib import Path
import pytest
from app.flow.messages import MessageSpec
from app.flow.schemas import FlowDef, NodeDef
from app.flow.store import FlowStore, StaleVersion
from fluksio.flow.messages import MessageSpec
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.store import FlowStore, StaleVersion
SOURCE = "def process():\n return {}\n"
EDITED = "def process():\n return {'temp': 1}\n"
+7 -7
View File
@@ -9,13 +9,13 @@ from pathlib import Path
import pytest
from app.api.routes.flows import snapshot_payload
from app.flow.controller import FlowController
from app.flow.events import EventBus, event_bus
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.store import FlowStore
from fluksio.api.routes.flows import snapshot_payload
from fluksio.flow.controller import FlowController
from fluksio.flow.events import EventBus, event_bus
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.store import FlowStore
def make_node(node_id: str, f, provides=()) -> Node:
+4 -4
View File
@@ -1,9 +1,9 @@
"""Message history: the series a node panel draws as a sparkline."""
from app.flow.messages import MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.state import HISTORY_LIMIT, MemoryState
from fluksio.flow.messages import MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.state import HISTORY_LIMIT, MemoryState
def emitter(values) -> Node:
+7 -7
View File
@@ -11,13 +11,13 @@ import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from app.flow.controller import HOOK_PREFIX, FlowController
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import HttpNode
from app.flow.pipeline import Pipeline
from app.flow.schemas import FlowDef, NodeDef
from app.flow.secrets import init_secrets, resolve_params
from app.flow.store import FlowStore
from fluksio.flow.controller import HOOK_PREFIX, FlowController
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import HttpNode
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.secrets import init_secrets, resolve_params
from fluksio.flow.store import FlowStore
SECRET = "d3vice-key"
HOOK = f"{HOOK_PREFIX}/house/sensor"
+3 -3
View File
@@ -4,9 +4,9 @@ from pathlib import Path
import pytest
from app.flow.messages import MessageSpec
from app.flow.schemas import FlowDef, NodeDef
from app.flow.store import FlowStore, LibExists, LibNotFound
from fluksio.flow.messages import MessageSpec
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.store import FlowStore, LibExists, LibNotFound
SOURCE = "def process():\n return {'temp': 1}\n"
+5 -5
View File
@@ -3,11 +3,11 @@
import sys
from typing import Any
from app.flow import logs
from app.flow.controller import with_settings
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from fluksio.flow import logs
from fluksio.flow.controller import with_settings
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
def run_with_capture(nodes: list[Node], bus: "RecordingBus") -> None:
+1 -1
View File
@@ -2,7 +2,7 @@ import json
import pytest
from app.flow.messages import DType, MessageSpec, flow_of, qualify
from fluksio.flow.messages import DType, MessageSpec, flow_of, qualify
def test_port_defaults_to_last_name_segment():
+2 -2
View File
@@ -6,8 +6,8 @@ from pathlib import Path
import pytest
from app.flow import modules
from app.flow.store import FlowStore
from fluksio.flow import modules
from fluksio.flow.store import FlowStore
pytestmark = pytest.mark.skipif(
shutil.which("uv") is None, reason="module management needs uv"
+6 -6
View File
@@ -9,12 +9,12 @@ from pathlib import Path
import pytest
from app.flow.controller import FlowController
from app.flow.messages import DType, MessageSpec
from app.flow.pipeline import Pipeline
from app.flow.schemas import FlowDef, NodeDef
from app.flow.state import MemoryState
from app.flow.store import FlowStore
from fluksio.flow.controller import FlowController
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.state import MemoryState
from fluksio.flow.store import FlowStore
SOURCE = "def process(reading, factor):\n return {'scaled': reading * factor}\n"
+5 -5
View File
@@ -6,8 +6,8 @@ only fails when someone places that node. Building one of each catches it.
import pytest
from app.flow.controller import NODE_TYPES, node_type_info
from app.flow.messages import DType, MessageSpec
from fluksio.flow.controller import NODE_TYPES, node_type_info
from fluksio.flow.messages import DType, MessageSpec
# Enough configuration for each type to construct; the ports decide the
# direction, so every type gets both an input and an output where it allows it.
@@ -160,7 +160,7 @@ def test_every_offered_type_has_a_fixture():
def test_a_flux_request_is_run_rather_than_written(monkeypatch):
"""A query passing through is not a point to store."""
from app.flow.nodes import InfluxDbNode
from fluksio.flow.nodes import InfluxDbNode
node = InfluxDbNode(
requires=[
@@ -199,8 +199,8 @@ def test_a_flux_request_is_run_rather_than_written(monkeypatch):
def test_a_falsy_return_is_a_mistake_not_silence():
"""Only None means "nothing to publish"."""
from app.flow.nodes import Node
from app.flow.nodes.base import NodeOutputError
from fluksio.flow.nodes import Node
from fluksio.flow.nodes.base import NodeOutputError
def make(retval):
return Node(
+4 -4
View File
@@ -1,9 +1,9 @@
"""The wiring fundamentals: name binding, fan-in, namespaces, validation."""
from app.flow.events import EventBus
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from fluksio.flow.events import EventBus
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
def spec(name: str, dtype: DType = DType.FLOAT, port: str = "") -> MessageSpec:
+7 -7
View File
@@ -5,19 +5,19 @@ actually published, it pulses all of them — and when the cause is a dashboard
control or another flow, it pulses a node that did nothing at all.
"""
from app.flow.dashboards import (
from fluksio.flow.dashboards import (
DashboardDef,
DashboardStore,
PageDef,
SectionDef,
WidgetDef,
)
from app.flow.events import EventBus
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline, ValueSource
from app.flow.state import MemoryState
from app.flow.store import FlowStore
from fluksio.flow.events import EventBus
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline, ValueSource
from fluksio.flow.state import MemoryState
from fluksio.flow.store import FlowStore
def collect(bus: EventBus) -> list[dict]:
+6 -6
View File
@@ -2,12 +2,12 @@
import time
from app.flow.executor import ExecutionService
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.queue import MemoryWorkQueue, WorkItem
from app.flow.state import MemoryState
from fluksio.flow.executor import ExecutionService
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.queue import MemoryWorkQueue, WorkItem
from fluksio.flow.state import MemoryState
def test_items_come_back_in_the_order_they_went_in():
+2 -2
View File
@@ -13,8 +13,8 @@ from collections.abc import Iterator
import pytest
from app.flow.remote import NoWorker, RemoteWorker, RemoteWorkerHub
from app.flow.workers import NodeTimeout, RemoteError
from fluksio.flow.remote import NoWorker, RemoteWorker, RemoteWorkerHub
from fluksio.flow.workers import NodeTimeout, RemoteError
@pytest.fixture
+6 -6
View File
@@ -8,10 +8,10 @@ parameters a caller sends are refused before anything runs if they are wrong.
import pytest
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import NodeOutcome, Pipeline
from app.flow.runs import (
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import NodeOutcome, Pipeline
from fluksio.flow.runs import (
MetricSink,
RunRejected,
batch_issues,
@@ -20,8 +20,8 @@ from app.flow.runs import (
required_labels,
seed_values,
)
from app.flow.schemas import FlowDef, FlowInput, NodeDef
from app.flow.state import MemoryState
from fluksio.flow.schemas import FlowDef, FlowInput, NodeDef
from fluksio.flow.state import MemoryState
def spec(name: str, dtype: DType = DType.FLOAT, **kwargs) -> MessageSpec:
+7 -7
View File
@@ -6,13 +6,13 @@ from typing import Any
from fastapi import FastAPI
from fastapi.testclient import TestClient
from app.api.deps import get_current_user
from app.api.routes.flows import router
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.schemas import FlowDef
from app.flow.store import FlowStore
from fluksio.api.deps import get_current_user
from fluksio.api.routes.flows import router
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.schemas import FlowDef
from fluksio.flow.store import FlowStore
def spec(name: str) -> MessageSpec:
+3 -3
View File
@@ -2,9 +2,9 @@
import asyncio
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import MqttNode
from app.flow.nodes.http import close_shared_client, shared_client
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import MqttNode
from fluksio.flow.nodes.http import close_shared_client, shared_client
def test_http_senders_share_one_pooled_client():
+4 -4
View File
@@ -5,10 +5,10 @@ running value in a message it both reads and writes. That is the sanctioned
shape, and these tests pin what it means.
"""
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.state import MemoryState
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.state import MemoryState
def counter() -> Node:
+3 -3
View File
@@ -3,9 +3,9 @@ from pathlib import Path
import pytest
from app.flow.messages import MessageSpec
from app.flow.schemas import FlowDef, NodeDef
from app.flow.store import FlowExists, FlowNotFound, FlowStore
from fluksio.flow.messages import MessageSpec
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.store import FlowExists, FlowNotFound, FlowStore
@pytest.fixture
+3 -3
View File
@@ -4,9 +4,9 @@ import asyncio
import pytest
from app.flow import supervision
from app.flow.events import EventBus
from app.flow.supervision import FAILURE_BUDGET, Supervisor
from fluksio.flow import supervision
from fluksio.flow.events import EventBus
from fluksio.flow.supervision import FAILURE_BUDGET, Supervisor
@pytest.fixture(autouse=True)
+4 -4
View File
@@ -6,10 +6,10 @@ atomic operations, so those are covered here too.
from concurrent.futures import ThreadPoolExecutor
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import Node
from app.flow.pipeline import Pipeline
from app.flow.state import MemoryState
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.state import MemoryState
def spec(name: str) -> MessageSpec:
+12 -5
View File
@@ -4,10 +4,17 @@ These are the shapes a Node-RED installation is mostly made of, so their
behaviour is worth pinning rather than just their construction.
"""
from app.flow.messages import DType, MessageSpec
from app.flow.nodes import ChangeNode, ExecNode, FileNode, JoinNode, RbeNode, SwitchNode
from app.flow.pipeline import Pipeline
from app.flow.state import MemoryState
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import (
ChangeNode,
ExecNode,
FileNode,
JoinNode,
RbeNode,
SwitchNode,
)
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.state import MemoryState
def spec(name: str, dtype: DType = DType.FLOAT) -> MessageSpec:
@@ -233,7 +240,7 @@ def test_a_file_node_refuses_to_leave_its_directory():
def test_a_file_round_trips_through_the_sandbox(tmp_path, monkeypatch):
from app.core.config import settings
from fluksio.core.config import settings
monkeypatch.setattr(settings, "FLOWS_DIR", tmp_path / "flows")
+3 -3
View File
@@ -2,9 +2,9 @@
from fastapi.testclient import TestClient
from app.flow.events import EventBus
from app.flow.watchdog import DEGRADED_STRIKES, LoopWatchdog
from app.main import app
from fluksio.flow.events import EventBus
from fluksio.flow.watchdog import DEGRADED_STRIKES, LoopWatchdog
from fluksio.main import app
def test_a_responsive_loop_stays_healthy():
+4 -4
View File
@@ -7,10 +7,10 @@ from collections.abc import Iterator
import pytest
from app.flow.artifacts import ArtifactStore
from app.flow.messages import DType, MessageSpec
from app.flow.worker_main import ARTIFACT_DIR_ENV
from app.flow.workers import NodeCancelled, NodeTimeout, PythonWorkerPool
from fluksio.flow.artifacts import ArtifactStore
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.worker_main import ARTIFACT_DIR_ENV
from fluksio.flow.workers import NodeCancelled, NodeTimeout, PythonWorkerPool
@pytest.fixture
+5 -5
View File
@@ -10,9 +10,9 @@ import httpx
import pytest
from fastapi.testclient import TestClient
from app.core import security
from app.core.config import settings
from app.main import app
from fluksio.core import security
from fluksio.core.config import settings
from fluksio.main import app
MCP_HEADERS = {"Accept": "application/json, text/event-stream"}
@@ -31,8 +31,8 @@ def over_mcp(monkeypatch: pytest.MonkeyPatch):
whole exchange happens inside a single ``asyncio.run``.
"""
monkeypatch.setattr(settings, "MCP_ENABLED", True)
from app.mcp import http as mcp_http
from app.mcp import server as mcp_server
from fluksio.mcp import http as mcp_http
from fluksio.mcp import server as mcp_server
# A FastMCP instance enters its session manager once, and another test in
# the run may have built one already.
@@ -2,7 +2,7 @@ from unittest.mock import MagicMock, patch
from sqlmodel import select
from app.backend_pre_start import init, logger
from fluksio.backend_pre_start import init, logger
def test_init_successful_connection() -> None:
@@ -14,8 +14,8 @@ def test_init_successful_connection() -> None:
select1 = select(1)
with (
patch("app.backend_pre_start.Session", return_value=session_mock),
patch("app.backend_pre_start.select", return_value=select1),
patch("fluksio.backend_pre_start.Session", return_value=session_mock),
patch("fluksio.backend_pre_start.select", return_value=select1),
patch.object(logger, "info"),
patch.object(logger, "error"),
patch.object(logger, "warn"),
+3 -3
View File
@@ -2,7 +2,7 @@ from unittest.mock import MagicMock, patch
from sqlmodel import select
from app.tests_pre_start import init, logger
from fluksio.tests_pre_start import init, logger
def test_init_successful_connection() -> None:
@@ -14,8 +14,8 @@ def test_init_successful_connection() -> None:
select1 = select(1)
with (
patch("app.tests_pre_start.Session", return_value=session_mock),
patch("app.tests_pre_start.select", return_value=select1),
patch("fluksio.tests_pre_start.Session", return_value=session_mock),
patch("fluksio.tests_pre_start.select", return_value=select1),
patch.object(logger, "info"),
patch.object(logger, "error"),
patch.object(logger, "warn"),
+10 -10
View File
@@ -18,11 +18,11 @@ from cryptography.hazmat.primitives.asymmetric import rsa
from fastapi.testclient import TestClient
from sqlmodel import Session
from app.api.deps import decode_token, user_from_token
from app.cloud import config as cloud_config
from app.core.config import settings
from app.flow.panels import PanelDef, PanelsConfig, write_config
from app.models import User
from fluksio.api.deps import decode_token, user_from_token
from fluksio.cloud import config as cloud_config
from fluksio.core.config import settings
from fluksio.flow.panels import PanelDef, PanelsConfig, write_config
from fluksio.models import User
from tests.utils.portal import ISSUER, portal_token
@@ -206,7 +206,7 @@ def test_adding_a_remote_user_maps_and_revokes(
return_value={"user_id": "portal-user-9", "email": "remote@example.com"}
),
)
with patch("app.api.routes.cloud.httpx.post", return_value=portal_reply) as post:
with patch("fluksio.api.routes.cloud.httpx.post", return_value=portal_reply) as post:
added = client.post(
f"{settings.API_V1_STR}/cloud/users",
headers=superuser_token_headers,
@@ -224,7 +224,7 @@ def test_adding_a_remote_user_maps_and_revokes(
resolved = user_from_token(db, theirs)
assert resolved is not None and resolved.email == "remote@example.com"
with patch("app.api.routes.cloud.httpx.post", return_value=portal_reply):
with patch("fluksio.api.routes.cloud.httpx.post", return_value=portal_reply):
again = client.post(
f"{settings.API_V1_STR}/cloud/users",
headers=superuser_token_headers,
@@ -233,7 +233,7 @@ def test_adding_a_remote_user_maps_and_revokes(
assert again.status_code == 409
with patch(
"app.api.routes.cloud.httpx.delete", return_value=Mock(status_code=200)
"fluksio.api.routes.cloud.httpx.delete", return_value=Mock(status_code=200)
) as delete:
removed = client.delete(
f"{settings.API_V1_STR}/users/{body['id']}", headers=superuser_token_headers
@@ -279,7 +279,7 @@ def test_enrolling_against_a_portal_without_an_owner_is_refused(
),
)
try:
with patch("app.api.routes.cloud.httpx.AsyncClient") as client_cls:
with patch("fluksio.api.routes.cloud.httpx.AsyncClient") as client_cls:
client_cls.return_value.__aenter__.return_value.post = AsyncMock(
return_value=reply
)
@@ -304,7 +304,7 @@ def test_an_older_enrolment_adopts_the_owner_on_attach(
again, which for a machine reached only through the portal means standing in
front of it.
"""
from app.cloud.connector import CloudConnector
from fluksio.cloud.connector import CloudConnector
enrolled.portal_sub = None
db.add(enrolled)
+3 -3
View File
@@ -10,9 +10,9 @@ from datetime import datetime, timezone
from sqlmodel import Session, select
from app.flow.events import EventBus
from app.flow.metrics import DETAIL_CAP, RUN_STALE_S, MetricsCollector
from app.models import EngineEvent, FlowRun, MetricBucket
from fluksio.flow.events import EventBus
from fluksio.flow.metrics import DETAIL_CAP, RUN_STALE_S, MetricsCollector
from fluksio.models import EngineEvent, FlowRun, MetricBucket
FLOW = "metrics-test"
NODE = "metrics-test.calc"
+3 -3
View File
@@ -1,9 +1,9 @@
from fastapi.testclient import TestClient
from sqlmodel import Session
from app import crud
from app.core.config import settings
from app.models import User, UserCreate, UserUpdate
from fluksio import crud
from fluksio.core.config import settings
from fluksio.models import User, UserCreate, UserUpdate
from tests.utils.utils import random_email, random_lower_string
+1 -1
View File
@@ -3,7 +3,7 @@ import string
from fastapi.testclient import TestClient
from app.core.config import settings
from fluksio.core.config import settings
def random_lower_string() -> str: