refactor: test row factories and the fetch stub have one copy each (3109)
CI and images / lint (push) Successful in 2s
CI and images / extension-version (push) Successful in 2s
CI and images / frontend-build (push) Successful in 20s
CI and images / backend-lint-and-test (push) Successful in 30s
CI and images / integration (push) Successful in 2m18s
CI and images / sign-extension (push) Successful in 3s
CI and images / build-agent (push) Successful in 6s
CI and images / build-web (push) Successful in 1m44s
CI and images / smoke-web (push) Successful in 56s
CI and images / promote (push) Skipped
CI and images / lint (push) Successful in 2s
CI and images / extension-version (push) Successful in 2s
CI and images / frontend-build (push) Successful in 20s
CI and images / backend-lint-and-test (push) Successful in 30s
CI and images / integration (push) Successful in 2m18s
CI and images / sign-extension (push) Successful in 3s
CI and images / build-agent (push) Successful in 6s
CI and images / build-web (push) Successful in 1m44s
CI and images / smoke-web (push) Successful in 56s
CI and images / promote (push) Skipped
tests/factories.py holds image_row/make_image/make_image_async/make_tag. The 17 byte-identical _img/_tag helpers (15 modules) now import them under their old names, so no call site changed. frontend/test/support/stubFetch.js replaces 15 copies that differed only in formatting. Copies whose bodies differ (other defaults, other columns, a url-only stub) are left as they are; folding those needs a look at each caller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
This commit is contained in:
@@ -1,23 +1,12 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useAdminStore } from '../src/stores/admin.js'
|
import { useAdminStore } from '../src/stores/admin.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
|
|
||||||
// Covers the two helpers the admin store actions route through (DRY Finding C,
|
// Covers the two helpers the admin store actions route through (DRY Finding C,
|
||||||
// #753): _dryRunPost (URL + dry_run body, sourceId→source_id) and _guard
|
// #753): _dryRunPost (URL + dry_run body, sourceId→source_id) and _guard
|
||||||
// (lastError capture + rethrow). The store had no frontend test before.
|
// (lastError capture + rethrow). The store had no frontend test before.
|
||||||
|
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function lastCallBody(calls) {
|
function lastCallBody(calls) {
|
||||||
return JSON.parse(calls.at(-1).init.body)
|
return JSON.parse(calls.at(-1).init.body)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useCredentialsStore } from '../src/stores/credentials.js'
|
import { useCredentialsStore } from '../src/stores/credentials.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status, statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('credentials store', () => {
|
describe('credentials store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,18 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useDbMaintenanceStore } from '../src/stores/dbMaintenance.js'
|
import { useDbMaintenanceStore } from '../src/stores/dbMaintenance.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('dbMaintenance store', () => {
|
describe('dbMaintenance store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useDownloadsStore } from '../src/stores/downloads.js'
|
import { useDownloadsStore } from '../src/stores/downloads.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status, statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('downloads store', () => {
|
describe('downloads store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,18 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { cloneFilter, filterToQuery, useGalleryStore } from '../src/stores/gallery.js'
|
import { cloneFilter, filterToQuery, useGalleryStore } from '../src/stores/gallery.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const EMPTY = { images: [], date_groups: [], next_cursor: null }
|
const EMPTY = { images: [], date_groups: [], next_cursor: null }
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useGallerySelectionStore } from '../src/stores/gallerySelection.js'
|
import { useGallerySelectionStore } from '../src/stores/gallerySelection.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('gallerySelection store', () => {
|
describe('gallerySelection store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { usePlatformsStore } from '../src/stores/platforms.js'
|
import { usePlatformsStore } from '../src/stores/platforms.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status, statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('platforms store', () => {
|
describe('platforms store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,18 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useProvenanceStore } from '../src/stores/provenance.js'
|
import { useProvenanceStore } from '../src/stores/provenance.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('provenance store', () => {
|
describe('provenance store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useSeriesManageStore, moveItem } from '../src/stores/seriesManage.js'
|
import { useSeriesManageStore, moveItem } from '../src/stores/seriesManage.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status, statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FC-6.x: a flat page run + cosmetic chapter dividers.
|
// FC-6.x: a flat page run + cosmetic chapter dividers.
|
||||||
const SERIES_BODY = {
|
const SERIES_BODY = {
|
||||||
|
|||||||
@@ -6,17 +6,7 @@ import {
|
|||||||
progressPct,
|
progressPct,
|
||||||
clampPage
|
clampPage
|
||||||
} from '../src/stores/seriesReader.js'
|
} from '../src/stores/seriesReader.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status, statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const M = [
|
const M = [
|
||||||
{ page_number: 1, top: 0, height: 100 },
|
{ page_number: 1, top: 0, height: 100 },
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useSourcesStore } from '../src/stores/sources.js'
|
import { useSourcesStore } from '../src/stores/sources.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status, statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('sources store', () => {
|
describe('sources store', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,21 +1,10 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useSuggestionsStore } from '../src/stores/suggestions.js'
|
import { useSuggestionsStore } from '../src/stores/suggestions.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
|
|
||||||
vi.mock('../src/utils/toast.js', () => ({ toast: vi.fn() }))
|
vi.mock('../src/utils/toast.js', () => ({ toast: vi.fn() }))
|
||||||
|
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every suggestion is a canonical DB tag now (tagging-v2): a real id, flagged
|
// Every suggestion is a canonical DB tag now (tagging-v2): a real id, flagged
|
||||||
// above/below its head's suggest threshold. No raw / creates-new / alias cases.
|
// above/below its head's suggest threshold. No raw / creates-new / alias cases.
|
||||||
const sugg = (over = {}) => ({
|
const sugg = (over = {}) => ({
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Replace globalThis.fetch with a stub answering from `handler(url, init)`,
|
||||||
|
// which returns { status, body }. Fifteen specs carried their own copy of this
|
||||||
|
// (#3109); a response shape change now has one place to go.
|
||||||
|
import { vi } from 'vitest'
|
||||||
|
|
||||||
|
export function stubFetch (handler) {
|
||||||
|
globalThis.fetch = vi.fn(async (url, init) => {
|
||||||
|
const { status, body } = handler(url, init)
|
||||||
|
return {
|
||||||
|
ok: status >= 200 && status < 300,
|
||||||
|
status,
|
||||||
|
statusText: String(status),
|
||||||
|
text: async () => (body == null ? '' : JSON.stringify(body))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,18 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useTagDirectoryStore } from '../src/stores/tagDirectory.js'
|
import { useTagDirectoryStore } from '../src/stores/tagDirectory.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('tagDirectory store: rename / merge', () => {
|
describe('tagDirectory store: rename / merge', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,18 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { useTagStore } from '../src/stores/tags.js'
|
import { useTagStore } from '../src/stores/tags.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('tags store: setFandom', () => {
|
describe('tags store: setFandom', () => {
|
||||||
beforeEach(() => setActivePinia(createPinia()))
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
||||||
import { setActivePinia, createPinia } from 'pinia'
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
import { laneStuckFor, useSystemActivityStore } from '../src/stores/systemActivity.js'
|
import { laneStuckFor, useSystemActivityStore } from '../src/stores/systemActivity.js'
|
||||||
|
import { stubFetch } from './support/stubFetch.js'
|
||||||
|
|
||||||
// Milestone 422 step 4. Covers the store half of the worker-lane dial — the
|
// Milestone 422 step 4. Covers the store half of the worker-lane dial — the
|
||||||
// part that decides what the card can tell the operator.
|
// part that decides what the card can tell the operator.
|
||||||
@@ -18,18 +19,6 @@ import { laneStuckFor, useSystemActivityStore } from '../src/stores/systemActivi
|
|||||||
// as one. A control that silently does nothing is worse than one that
|
// as one. A control that silently does nothing is worse than one that
|
||||||
// refuses out loud.
|
// refuses out loud.
|
||||||
|
|
||||||
function stubFetch(handler) {
|
|
||||||
globalThis.fetch = vi.fn(async (url, init) => {
|
|
||||||
const { status, body } = handler(url, init)
|
|
||||||
return {
|
|
||||||
ok: status >= 200 && status < 300,
|
|
||||||
status,
|
|
||||||
statusText: String(status),
|
|
||||||
text: async () => (body == null ? '' : JSON.stringify(body)),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const LANES_BODY = {
|
const LANES_BODY = {
|
||||||
lanes: [
|
lanes: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
"""Throwaway rows for tests: one copy of the placeholder columns (#3109).
|
||||||
|
|
||||||
|
`ImageRecord` needs a unique path and sha256 plus six NOT NULL columns no test
|
||||||
|
cares about. Fifteen modules re-typed the same builder, so a new NOT NULL column
|
||||||
|
meant fifteen separate patches. The tests that need these rows import them from
|
||||||
|
here, usually under their old local name (`make_image as _img`), so their call
|
||||||
|
sites did not change.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from backend.app.models import ImageRecord, Tag, TagKind
|
||||||
|
|
||||||
|
|
||||||
|
def image_row(sha: str, emb=None, **overrides) -> ImageRecord:
|
||||||
|
"""An unsaved ImageRecord keyed by `sha`; `emb` is its SigLIP embedding."""
|
||||||
|
fields = {
|
||||||
|
"path": f"/images/{sha}.jpg", "sha256": sha, "size_bytes": 1,
|
||||||
|
"mime": "image/jpeg", "width": 1, "height": 1,
|
||||||
|
"origin": "imported_filesystem", "integrity_status": "unknown",
|
||||||
|
}
|
||||||
|
if emb is not None:
|
||||||
|
fields["siglip_embedding"] = emb
|
||||||
|
fields.update(overrides)
|
||||||
|
return ImageRecord(**fields)
|
||||||
|
|
||||||
|
|
||||||
|
def make_image(db, sha: str, emb=None, **overrides) -> ImageRecord:
|
||||||
|
"""image_row, added and flushed on a sync session."""
|
||||||
|
img = image_row(sha, emb, **overrides)
|
||||||
|
db.add(img)
|
||||||
|
db.flush()
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
async def make_image_async(db, sha: str, emb=None, **overrides) -> ImageRecord:
|
||||||
|
"""image_row, added and flushed on an async session."""
|
||||||
|
img = image_row(sha, emb, **overrides)
|
||||||
|
db.add(img)
|
||||||
|
await db.flush()
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
def make_tag(db, name: str, **overrides) -> Tag:
|
||||||
|
"""A general tag, added and flushed on a sync session."""
|
||||||
|
tag = Tag(**{"name": name, "kind": TagKind.general, **overrides})
|
||||||
|
db.add(tag)
|
||||||
|
db.flush()
|
||||||
|
return tag
|
||||||
+1
-10
@@ -4,6 +4,7 @@ import pytest
|
|||||||
from backend.app.models import ImageRecord, ImageRegion, TagKind
|
from backend.app.models import ImageRecord, ImageRegion, TagKind
|
||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.tag_service import TagService
|
from backend.app.services.tag_service import TagService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -14,16 +15,6 @@ def _ccip(slot: int) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
async def _figure(db, image_id, ccip):
|
async def _figure(db, image_id, ccip):
|
||||||
db.add(ImageRegion(
|
db.add(ImageRegion(
|
||||||
image_record_id=image_id, kind="figure", rx=0.0, ry=0.0, rw=1.0, rh=1.0,
|
image_record_id=image_id, kind="figure", rx=0.0, ry=0.0, rw=1.0, rh=1.0,
|
||||||
|
|||||||
+1
-10
@@ -7,20 +7,11 @@ from sqlalchemy import func, select
|
|||||||
from backend.app.models import GpuJob, ImageRecord
|
from backend.app.models import GpuJob, ImageRecord
|
||||||
from backend.app.services.ml.gpu_jobs import GpuJobService
|
from backend.app.services.ml.gpu_jobs import GpuJobService
|
||||||
from backend.app.services.ml.regions import RegionService
|
from backend.app.services.ml.regions import RegionService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_agent_endpoints_require_bearer(client, db):
|
async def test_agent_endpoints_require_bearer(client, db):
|
||||||
resp = await client.post("/api/gpu/jobs/lease", json={"agent_id": "a1"})
|
resp = await client.post("/api/gpu/jobs/lease", json={"agent_id": "a1"})
|
||||||
|
|||||||
@@ -5,20 +5,11 @@ from backend.app.models import ImageRecord, TagHead, TagKind
|
|||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.models.tag_suggestion_rejection import TagSuggestionRejection
|
from backend.app.models.tag_suggestion_rejection import TagSuggestionRejection
|
||||||
from backend.app.services.tag_service import TagService
|
from backend.app.services.tag_service import TagService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
async def _apply(db, image_id, tag_id, source):
|
async def _apply(db, image_id, tag_id, source):
|
||||||
await db.execute(image_tag.insert().values(
|
await db.execute(image_tag.insert().values(
|
||||||
image_record_id=image_id, tag_id=tag_id, source=source,
|
image_record_id=image_id, tag_id=tag_id, source=source,
|
||||||
|
|||||||
+1
-10
@@ -13,6 +13,7 @@ from backend.app.models import (
|
|||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.ml.ccip import match_image
|
from backend.app.services.ml.ccip import match_image
|
||||||
from backend.app.services.tag_service import TagService
|
from backend.app.services.tag_service import TagService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -23,16 +24,6 @@ def _ccip(slot: int) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
async def _figure(db, image_id, ccip):
|
async def _figure(db, image_id, ccip):
|
||||||
db.add(ImageRegion(
|
db.add(ImageRegion(
|
||||||
image_record_id=image_id, kind="figure",
|
image_record_id=image_id, kind="figure",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from backend.app.models.tag import image_tag
|
|||||||
from backend.app.services.ml.character_prototypes import (
|
from backend.app.services.ml.character_prototypes import (
|
||||||
refresh_character_prototypes,
|
refresh_character_prototypes,
|
||||||
)
|
)
|
||||||
|
from tests.factories import make_image as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -28,17 +29,6 @@ def _ccip(slot: int = 0) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def _img(db, sha: str) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _figure(db, image_id: int, ccip=None) -> None:
|
def _figure(db, image_id: int, ccip=None) -> None:
|
||||||
db.add(ImageRegion(
|
db.add(ImageRegion(
|
||||||
image_record_id=image_id, kind="figure",
|
image_record_id=image_id, kind="figure",
|
||||||
|
|||||||
+1
-10
@@ -10,20 +10,11 @@ from backend.app.services.ml.gpu_jobs import (
|
|||||||
PENDING_POISON_CAP,
|
PENDING_POISON_CAP,
|
||||||
GpuJobService,
|
GpuJobService,
|
||||||
)
|
)
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_enqueue_siglip_backfill_gates_on_concept_region(db):
|
async def test_enqueue_siglip_backfill_gates_on_concept_region(db):
|
||||||
# 'siglip' backfill enqueues images that lack a concept region (the
|
# 'siglip' backfill enqueues images that lack a concept region (the
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from backend.app.models import (
|
|||||||
)
|
)
|
||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.ml.heads import auto_apply_sweep
|
from backend.app.services.ml.heads import auto_apply_sweep
|
||||||
|
from tests.factories import make_image as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -24,17 +25,6 @@ def _emb(slot: int) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def _img(db, sha: str, emb) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown", siglip_embedding=emb,
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _head(db, tag_id: int, slot: int, *, threshold=0.5, n_pos=60):
|
def _head(db, tag_id: int, slot: int, *, threshold=0.5, n_pos=60):
|
||||||
s = db.execute(select(MLSettings).where(MLSettings.id == 1)).scalar_one()
|
s = db.execute(select(MLSettings).where(MLSettings.id == 1)).scalar_one()
|
||||||
w = [0.0] * 1152
|
w = [0.0] * 1152
|
||||||
|
|||||||
@@ -17,28 +17,12 @@ from backend.app.services.ml.heads import (
|
|||||||
_head_fingerprints,
|
_head_fingerprints,
|
||||||
_heads_needing_retrain,
|
_heads_needing_retrain,
|
||||||
)
|
)
|
||||||
|
from tests.factories import make_image as _img
|
||||||
|
from tests.factories import make_tag as _tag
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
def _img(db, sha: str) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _tag(db, name: str) -> Tag:
|
|
||||||
t = Tag(name=name, kind=TagKind.general)
|
|
||||||
db.add(t)
|
|
||||||
db.flush()
|
|
||||||
return t
|
|
||||||
|
|
||||||
|
|
||||||
def _apply(db, image_id: int, tag_id: int) -> None:
|
def _apply(db, image_id: int, tag_id: int) -> None:
|
||||||
db.execute(image_tag.insert().values(
|
db.execute(image_tag.insert().values(
|
||||||
image_record_id=image_id, tag_id=tag_id, source="manual",
|
image_record_id=image_id, tag_id=tag_id, source="manual",
|
||||||
|
|||||||
@@ -6,20 +6,11 @@ from sqlalchemy import select
|
|||||||
from backend.app.models import HeadMetric, HeadMetricsSnapshot, ImageRecord, TagHead, TagKind
|
from backend.app.models import HeadMetric, HeadMetricsSnapshot, ImageRecord, TagHead, TagKind
|
||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.tag_service import TagService
|
from backend.app.services.tag_service import TagService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _head(tag_id):
|
def _head(tag_id):
|
||||||
return TagHead(
|
return TagHead(
|
||||||
tag_id=tag_id, embedding_version="siglip-test", weights=[0.0] * 1152,
|
tag_id=tag_id, embedding_version="siglip-test", weights=[0.0] * 1152,
|
||||||
|
|||||||
@@ -8,28 +8,12 @@ from backend.app.models import ImageRecord, Tag, TagKind, TagPositiveConfirmatio
|
|||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.ml.heads import _eligible_tag_ids
|
from backend.app.services.ml.heads import _eligible_tag_ids
|
||||||
from backend.app.services.ml.training_data import _ids_with_tag
|
from backend.app.services.ml.training_data import _ids_with_tag
|
||||||
|
from tests.factories import make_image as _img
|
||||||
|
from tests.factories import make_tag as _tag
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
def _img(db, sha: str) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _tag(db, name: str) -> Tag:
|
|
||||||
t = Tag(name=name, kind=TagKind.general)
|
|
||||||
db.add(t)
|
|
||||||
db.flush()
|
|
||||||
return t
|
|
||||||
|
|
||||||
|
|
||||||
def _apply(db, image_id: int, tag_id: int, source: str) -> None:
|
def _apply(db, image_id: int, tag_id: int, source: str) -> None:
|
||||||
db.execute(image_tag.insert().values(
|
db.execute(image_tag.insert().values(
|
||||||
image_record_id=image_id, tag_id=tag_id, source=source,
|
image_record_id=image_id, tag_id=tag_id, source=source,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from backend.app.services.ml.allowlist import AllowlistService
|
|||||||
from backend.app.services.ml.heads import ground_applied_tag
|
from backend.app.services.ml.heads import ground_applied_tag
|
||||||
from backend.app.services.ml.suggestions import SuggestionService
|
from backend.app.services.ml.suggestions import SuggestionService
|
||||||
from backend.app.services.tag_service import TagService
|
from backend.app.services.tag_service import TagService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -22,17 +23,6 @@ def _emb(slot: int, val: float = 3.0) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha: str, emb=None) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown", siglip_embedding=emb,
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
async def _embver(db) -> str:
|
async def _embver(db) -> str:
|
||||||
s = (await db.execute(select(MLSettings).where(MLSettings.id == 1))).scalar_one()
|
s = (await db.execute(select(MLSettings).where(MLSettings.id == 1))).scalar_one()
|
||||||
return s.embedder_model_version
|
return s.embedder_model_version
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from backend.app.services.ml.heads import (
|
|||||||
auto_apply_sweep,
|
auto_apply_sweep,
|
||||||
system_tag_auto_apply_sweep,
|
system_tag_auto_apply_sweep,
|
||||||
)
|
)
|
||||||
|
from tests.factories import make_image as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -27,17 +28,6 @@ def _emb(slot: int) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def _img(db, sha: str, emb) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown", siglip_embedding=emb,
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _head(db, tag_id: int, slot: int, *, weight=1.0):
|
def _head(db, tag_id: int, slot: int, *, weight=1.0):
|
||||||
# weight 3.0 → score sigmoid(3)=0.95 clears the 0.90 presentation floor;
|
# weight 3.0 → score sigmoid(3)=0.95 clears the 0.90 presentation floor;
|
||||||
# weight 1.0 → sigmoid(1)=0.73 clears the 0.50 conflict floor.
|
# weight 1.0 → sigmoid(1)=0.73 clears the 0.50 conflict floor.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from backend.app.models import (
|
|||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.ml.heads import system_tag_auto_apply_sweep
|
from backend.app.services.ml.heads import system_tag_auto_apply_sweep
|
||||||
from backend.app.services.ml.training_data import _ids_with_tag
|
from backend.app.services.ml.training_data import _ids_with_tag
|
||||||
|
from tests.factories import make_image as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -26,17 +27,6 @@ def _emb(slot: int) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def _img(db, sha: str, emb) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown", siglip_embedding=emb,
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
def _head(db, tag_id: int, slot: int, *, weight=1.0):
|
def _head(db, tag_id: int, slot: int, *, weight=1.0):
|
||||||
s = db.execute(select(MLSettings).where(MLSettings.id == 1)).scalar_one()
|
s = db.execute(select(MLSettings).where(MLSettings.id == 1)).scalar_one()
|
||||||
w = [0.0] * 1152
|
w = [0.0] * 1152
|
||||||
|
|||||||
+1
-10
@@ -3,20 +3,11 @@ import pytest
|
|||||||
|
|
||||||
from backend.app.models import ImageRecord
|
from backend.app.models import ImageRecord
|
||||||
from backend.app.services.ml.regions import RegionService
|
from backend.app.services.ml.regions import RegionService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem", integrity_status="unknown",
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_replace_and_get_regions(db):
|
async def test_replace_and_get_regions(db):
|
||||||
img = await _img(db, "a" * 64)
|
img = await _img(db, "a" * 64)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from backend.app.models import ImageRecord, MLSettings, TagHead, TagKind
|
|||||||
from backend.app.models.tag import image_tag
|
from backend.app.models.tag import image_tag
|
||||||
from backend.app.services.ml.suggestions import SuggestionService
|
from backend.app.services.ml.suggestions import SuggestionService
|
||||||
from backend.app.services.tag_service import TagService
|
from backend.app.services.tag_service import TagService
|
||||||
|
from tests.factories import make_image_async as _img
|
||||||
|
|
||||||
pytestmark = pytest.mark.integration
|
pytestmark = pytest.mark.integration
|
||||||
|
|
||||||
@@ -17,17 +18,6 @@ def _emb(slot: int) -> list[float]:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
async def _img(db, sha: str, emb=None) -> ImageRecord:
|
|
||||||
img = ImageRecord(
|
|
||||||
path=f"/images/{sha}.jpg", sha256=sha, size_bytes=1, mime="image/jpeg",
|
|
||||||
width=1, height=1, origin="imported_filesystem",
|
|
||||||
integrity_status="unknown", siglip_embedding=emb,
|
|
||||||
)
|
|
||||||
db.add(img)
|
|
||||||
await db.flush()
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
async def _head(db, tag_id: int, slot: int = 0):
|
async def _head(db, tag_id: int, slot: int = 0):
|
||||||
s = (await db.execute(select(MLSettings).where(MLSettings.id == 1))).scalar_one()
|
s = (await db.execute(select(MLSettings).where(MLSettings.id == 1))).scalar_one()
|
||||||
weights = [0.0] * 1152
|
weights = [0.0] * 1152
|
||||||
|
|||||||
Reference in New Issue
Block a user