update: ruff check --fix
This commit is contained in:
@@ -2,21 +2,20 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from common.auth.passwords import hash_password
|
||||
from common.db.models import Roles, Users, WorkspaceMembers
|
||||
from common.ids import new_ulid
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy import delete, func, or_, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.db.models import Roles, Users, WorkspaceMembers
|
||||
from common.ids import new_ulid
|
||||
from common.auth.passwords import hash_password
|
||||
from backend.dependencies import (
|
||||
RequestContext,
|
||||
database_session,
|
||||
request_context,
|
||||
)
|
||||
|
||||
|
||||
router = APIRouter(prefix="/api/v1/admin", tags=["admin"])
|
||||
|
||||
|
||||
|
||||
@@ -16,18 +16,17 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import database_session, load_user_permissions
|
||||
from common.auth.jwt import JwtError, issue_jwt, verify_jwt_token
|
||||
from common.auth.membership import resolve_is_system_admin
|
||||
from common.auth.passwords import verify_password
|
||||
from common.config import settings
|
||||
from common.db.models import Roles, Users, WorkspaceMembers, Workspaces
|
||||
from common.ids import new_ulid
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import database_session, load_user_permissions
|
||||
|
||||
router = APIRouter(tags=["auth"])
|
||||
|
||||
|
||||
@@ -27,12 +27,8 @@ for.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import AsyncIterator
|
||||
from dataclasses import dataclass
|
||||
from typing import AsyncIterator
|
||||
|
||||
from fastapi import Depends, HTTPException, Query, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.auth.jwt import JwtError, verify_jwt_token
|
||||
from common.auth.membership import (
|
||||
@@ -43,7 +39,9 @@ from common.auth.membership import (
|
||||
from common.db import session_scope
|
||||
from common.db.models import Permissions, RolePermissions, Roles, Users, Workspaces
|
||||
from common.ids import new_ulid
|
||||
|
||||
from fastapi import Depends, HTTPException, Query, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
ACCESS_TOKEN_COOKIE = "access_token"
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
from common.auth.jwt import JwtError, verify_jwt_token
|
||||
from common.auth.membership import MembershipError, load_active_membership
|
||||
@@ -19,7 +18,7 @@ security = HTTPBearer(auto_error=False)
|
||||
def extract_notebook_path(
|
||||
uri: str,
|
||||
workspace_id: str,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Pull the relative notebook path out of the original request URI.
|
||||
|
||||
Only ``/jupyter/{workspace_id}/notebooks/*.ipynb`` requests are
|
||||
@@ -83,7 +82,7 @@ async def load_active_membership_or_403(
|
||||
async def verify_jupyter_access(
|
||||
request: Request,
|
||||
response: Response,
|
||||
auth: Optional[HTTPAuthorizationCredentials] = Depends(security),
|
||||
auth: HTTPAuthorizationCredentials | None = Depends(security),
|
||||
session: AsyncSession = Depends(database_session),
|
||||
) -> dict:
|
||||
"""Nginx auth_request subrequest handler.
|
||||
|
||||
@@ -65,12 +65,6 @@ import re
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Literal
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy import func, insert, or_, select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import current_user, database_session
|
||||
from common.auth.passwords import hash_password
|
||||
from common.db.models import (
|
||||
Permissions,
|
||||
@@ -81,7 +75,12 @@ from common.db.models import (
|
||||
Workspaces,
|
||||
)
|
||||
from common.ids import new_ulid
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy import func, insert, or_, select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import current_user, database_session
|
||||
|
||||
router = APIRouter(prefix="/api/v1/platform", tags=["platform"])
|
||||
|
||||
@@ -1240,7 +1239,7 @@ async def patch_role_permissions(
|
||||
|
||||
|
||||
__all__ = [
|
||||
"router",
|
||||
"SystemAdminContext",
|
||||
"router",
|
||||
"system_admin_context",
|
||||
]
|
||||
@@ -1,23 +1,21 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import os
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, Header, HTTPException, Query, Request, status
|
||||
from sqlalchemy import or_, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.db.models import DataResources, StorageObjects
|
||||
from common.ids import new_ulid
|
||||
from common.storage import workspaces_root
|
||||
from common.storage.schemas import (
|
||||
CreateUploadRequest,
|
||||
DownloadUrlRequest,
|
||||
ServerObjectRequest,
|
||||
)
|
||||
from fastapi import APIRouter, Depends, Header, HTTPException, Query, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import (
|
||||
RequestContext,
|
||||
database_session,
|
||||
@@ -27,11 +25,10 @@ from backend.schemas import (
|
||||
CompleteResourceUploadRequest,
|
||||
CreateResourceUploadRequest,
|
||||
DownloadUrlRequest,
|
||||
ResourceRelativePathRequest,
|
||||
)
|
||||
from backend.schemas import ResourceRelativePathRequest
|
||||
from backend.services.storage import (
|
||||
create_download_url_payload,
|
||||
create_server_object_payload,
|
||||
create_upload_record,
|
||||
soft_delete_object,
|
||||
upload_bytes_to_session,
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Any
|
||||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RuntimeClientError(Exception):
|
||||
status_code: int
|
||||
|
||||
@@ -4,6 +4,22 @@ from datetime import UTC, datetime
|
||||
from typing import Any, Literal
|
||||
from urllib.parse import quote
|
||||
|
||||
from common.config import settings
|
||||
from common.db.models import (
|
||||
ScheduleNodeRuns,
|
||||
ScheduleRuns,
|
||||
StorageObjects,
|
||||
)
|
||||
from common.scheduler import (
|
||||
DagTooLarge,
|
||||
InvalidDag,
|
||||
InvalidNodeArguments,
|
||||
ScheduleNotFound,
|
||||
TriggerError,
|
||||
create_scheduled_run,
|
||||
normalize_idempotency_key,
|
||||
)
|
||||
from common.schemas import StrictModel
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
Depends,
|
||||
@@ -18,29 +34,11 @@ from pydantic import Field
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.config import settings
|
||||
from common.db.models import (
|
||||
ScheduleNodeRuns,
|
||||
ScheduleRuns,
|
||||
StorageObjects,
|
||||
)
|
||||
from backend.dependencies import (
|
||||
RequestContext,
|
||||
database_session,
|
||||
request_context,
|
||||
)
|
||||
from common.schemas import StrictModel
|
||||
from common.scheduler import (
|
||||
DagTooLarge,
|
||||
InvalidDag,
|
||||
InvalidNodeArguments,
|
||||
ScheduleNotFound,
|
||||
TriggerError,
|
||||
create_scheduled_run,
|
||||
normalize_idempotency_key,
|
||||
)
|
||||
from common.ids import new_ulid
|
||||
|
||||
|
||||
router = APIRouter(tags=["schedule-runs"])
|
||||
RunStatus = Literal[
|
||||
|
||||
@@ -3,10 +3,9 @@ from __future__ import annotations
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic import Field, field_validator, model_validator
|
||||
|
||||
from common.db.models.schedules import FailurePolicy, PythonVersion, TriggerType
|
||||
from common.schemas import StrictModel
|
||||
from pydantic import Field, field_validator, model_validator
|
||||
|
||||
|
||||
def _required_text(value: str) -> str:
|
||||
@@ -40,7 +39,7 @@ class CreateScheduleRequest(StrictModel):
|
||||
return normalized or None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_trigger(self) -> "CreateScheduleRequest":
|
||||
def validate_trigger(self) -> CreateScheduleRequest:
|
||||
if self.trigger_type == "cron" and not self.cron_expression:
|
||||
raise ValueError("cron_expression is required for cron schedules")
|
||||
if self.trigger_type != "cron" and self.cron_expression:
|
||||
@@ -78,17 +77,17 @@ class UpdateScheduleRequest(StrictModel):
|
||||
return normalized or None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def require_change(self) -> "UpdateScheduleRequest":
|
||||
def require_change(self) -> UpdateScheduleRequest:
|
||||
if self.model_fields_set == {"workflow_version"}:
|
||||
raise ValueError("at least one schedule field must be updated")
|
||||
for field in {
|
||||
for field in (
|
||||
"schedule_name",
|
||||
"trigger_type",
|
||||
"timezone",
|
||||
"enabled",
|
||||
"max_concurrency",
|
||||
"failure_policy",
|
||||
}:
|
||||
):
|
||||
if field in self.model_fields_set and getattr(self, field) is None:
|
||||
raise ValueError(f"{field} cannot be null")
|
||||
return self
|
||||
@@ -158,7 +157,7 @@ class UpdateScheduleNodeRequest(StrictModel):
|
||||
return _required_text(value) if value is not None else None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def require_change(self) -> "UpdateScheduleNodeRequest":
|
||||
def require_change(self) -> UpdateScheduleNodeRequest:
|
||||
if self.model_fields_set == {"workflow_version"}:
|
||||
raise ValueError("at least one node field must be updated")
|
||||
for field in self.model_fields_set - {"workflow_version"}:
|
||||
@@ -182,7 +181,7 @@ class CreateScheduleEdgeRequest(StrictModel):
|
||||
return normalized or None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def reject_self_edge(self) -> "CreateScheduleEdgeRequest":
|
||||
def reject_self_edge(self) -> CreateScheduleEdgeRequest:
|
||||
if self.source_node_id == self.target_node_id:
|
||||
raise ValueError("an edge cannot connect a node to itself")
|
||||
return self
|
||||
|
||||
@@ -6,11 +6,6 @@ from decimal import Decimal
|
||||
from typing import Any
|
||||
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
||||
|
||||
from croniter import CroniterBadCronError, croniter
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy import delete, func, or_, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from common.db.models import (
|
||||
ScheduleEdges,
|
||||
ScheduleNodeRuns,
|
||||
@@ -20,6 +15,11 @@ from common.db.models import (
|
||||
Versions,
|
||||
)
|
||||
from common.ids import new_ulid
|
||||
from croniter import CroniterBadCronError, croniter
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
from sqlalchemy import delete, func, or_, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.dependencies import (
|
||||
RequestContext,
|
||||
database_session,
|
||||
@@ -36,7 +36,6 @@ from backend.schedule_schemas import (
|
||||
WorkflowVersionRequest,
|
||||
)
|
||||
|
||||
|
||||
router = APIRouter(tags=["schedules"])
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
@@ -15,13 +14,12 @@ from common.db.models import (
|
||||
Versions,
|
||||
)
|
||||
from common.ids import new_ulid
|
||||
from common.storage.schemas import ServerObjectRequest
|
||||
from common.storage import actual_bucket_name, build_storage_uri
|
||||
from common.storage.schemas import ServerObjectRequest
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
BackgroundTasks,
|
||||
Depends,
|
||||
Header,
|
||||
HTTPException,
|
||||
Query,
|
||||
Request,
|
||||
@@ -46,10 +44,10 @@ from backend.schemas import (
|
||||
UpdateScriptRequest,
|
||||
)
|
||||
from backend.services.storage import (
|
||||
_resolve_unique_object_key,
|
||||
create_download_url_payload,
|
||||
create_server_object_payload,
|
||||
soft_delete_object,
|
||||
_resolve_unique_object_key,
|
||||
)
|
||||
|
||||
router = APIRouter(tags=["scripts"])
|
||||
@@ -202,9 +200,7 @@ def script_payload(
|
||||
workspace_prefix = f"{script.workspace_id}/"
|
||||
if object_key:
|
||||
jupyter_path = (
|
||||
object_key[len(workspace_prefix) :]
|
||||
if object_key.startswith(workspace_prefix)
|
||||
else object_key
|
||||
object_key.removeprefix(workspace_prefix)
|
||||
)
|
||||
else:
|
||||
jupyter_path = _jupyter_path(script.script_type, script.script_id)
|
||||
|
||||
@@ -35,21 +35,19 @@ from datetime import timedelta
|
||||
from pathlib import PurePosixPath
|
||||
from typing import Any
|
||||
|
||||
from fastapi import HTTPException, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from common.config import settings
|
||||
from common.db.models import StorageObjects, UploadSessions
|
||||
from common.ids import new_ulid
|
||||
from common.storage import USAGE_TYPE_TO_PURPOSE, actual_bucket_name, build_storage_uri
|
||||
from common.storage.schemas import (
|
||||
CreateUploadRequest,
|
||||
DownloadUrlRequest,
|
||||
ServerObjectRequest,
|
||||
)
|
||||
from common.storage import USAGE_TYPE_TO_PURPOSE, actual_bucket_name, build_storage_uri
|
||||
|
||||
from fastapi import HTTPException, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
# ── shared low-level helpers (module-private) ────────────────────────────
|
||||
|
||||
@@ -91,7 +89,7 @@ def _safe_path_segment(segment: str) -> str:
|
||||
|
||||
|
||||
def _utcnow_naive() -> Any:
|
||||
from datetime import datetime, UTC
|
||||
from datetime import UTC, datetime
|
||||
return datetime.now(UTC).replace(tzinfo=None)
|
||||
|
||||
|
||||
@@ -207,9 +205,8 @@ async def create_upload_record(
|
||||
when the idempotency key hits an already-completed upload.
|
||||
"""
|
||||
from backend.storage_api import (
|
||||
require_workspace_member,
|
||||
normalized_idempotency_key,
|
||||
BUCKET_FOR_USAGE,
|
||||
require_workspace_member,
|
||||
)
|
||||
|
||||
workspace = await require_workspace_member(
|
||||
@@ -236,6 +233,7 @@ async def create_upload_record(
|
||||
upload = existing
|
||||
else:
|
||||
from datetime import timedelta
|
||||
|
||||
from backend.storage_api import utcnow
|
||||
|
||||
bucket_name = _resolve_bucket_for_usage(
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from collections.abc import AsyncIterator
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from pathlib import PurePosixPath
|
||||
from typing import Any, AsyncIterator
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from typing import Any
|
||||
|
||||
from common.config import settings
|
||||
from common.db import session_scope
|
||||
@@ -25,6 +22,10 @@ from common.storage.schemas import (
|
||||
DownloadUrlRequest,
|
||||
ServerObjectRequest,
|
||||
)
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.services.storage import (
|
||||
create_download_url_payload,
|
||||
create_server_object_payload,
|
||||
@@ -44,7 +45,7 @@ def hash_bytes(value: str) -> bytes:
|
||||
|
||||
def normalized_idempotency_key(workspace_id: str, user_id: str, value: str) -> str:
|
||||
digest = hashlib.sha256(
|
||||
f"{workspace_id}:{user_id}:{value}".encode("utf-8")
|
||||
f"{workspace_id}:{user_id}:{value}".encode()
|
||||
).hexdigest()
|
||||
return f"v1:{digest}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user