commit
43a6630527
@ -0,0 +1,34 @@
|
||||
import { useLanguages } from "@/apis/hooks";
|
||||
import { Selector, SelectorProps } from "@/components/inputs";
|
||||
import { useSelectorOptions } from "@/utilities";
|
||||
import { FunctionComponent, useMemo } from "react";
|
||||
|
||||
interface LanguageSelectorProps
|
||||
extends Omit<SelectorProps<Language.Server>, "options" | "getkey"> {
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
const LanguageSelector: FunctionComponent<LanguageSelectorProps> = ({
|
||||
enabled = false,
|
||||
...selector
|
||||
}) => {
|
||||
const { data } = useLanguages();
|
||||
|
||||
const filteredData = useMemo(() => {
|
||||
if (enabled) {
|
||||
return data?.filter((value) => value.enabled);
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}, [data, enabled]);
|
||||
|
||||
const options = useSelectorOptions(
|
||||
filteredData ?? [],
|
||||
(value) => value.name,
|
||||
(value) => value.code3
|
||||
);
|
||||
|
||||
return <Selector {...options} searchable {...selector}></Selector>;
|
||||
};
|
||||
|
||||
export default LanguageSelector;
|
@ -0,0 +1,196 @@
|
||||
import {
|
||||
decodeEqualData,
|
||||
encodeEqualData,
|
||||
LanguageEqualData,
|
||||
LanguageEqualImmediateData,
|
||||
} from "@/pages/Settings/Languages/equals";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
describe("Equals Parser", () => {
|
||||
it("should parse from string correctly", () => {
|
||||
interface TestData {
|
||||
text: string;
|
||||
expected: LanguageEqualImmediateData;
|
||||
}
|
||||
|
||||
function testParsedResult(
|
||||
text: string,
|
||||
expected: LanguageEqualImmediateData
|
||||
) {
|
||||
const result = decodeEqualData(text);
|
||||
|
||||
if (result === undefined) {
|
||||
expect(false, `Cannot parse '${text}' as language equal data`);
|
||||
return;
|
||||
}
|
||||
|
||||
expect(
|
||||
result,
|
||||
`${text} does not match with the expected equal data`
|
||||
).toStrictEqual(expected);
|
||||
}
|
||||
|
||||
const testValues: TestData[] = [
|
||||
{
|
||||
text: "spa-MX:spa",
|
||||
expected: {
|
||||
source: {
|
||||
content: "spa-MX",
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
target: {
|
||||
content: "spa",
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "zho@hi:zht",
|
||||
expected: {
|
||||
source: {
|
||||
content: "zho",
|
||||
hi: true,
|
||||
forced: false,
|
||||
},
|
||||
target: {
|
||||
content: "zht",
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "es-MX@forced:es-MX",
|
||||
expected: {
|
||||
source: {
|
||||
content: "es-MX",
|
||||
hi: false,
|
||||
forced: true,
|
||||
},
|
||||
target: {
|
||||
content: "es-MX",
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "en:en@hi",
|
||||
expected: {
|
||||
source: {
|
||||
content: "en",
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
target: {
|
||||
content: "en",
|
||||
hi: true,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
testValues.forEach((data) => {
|
||||
testParsedResult(data.text, data.expected);
|
||||
});
|
||||
});
|
||||
|
||||
it("should encode to string correctly", () => {
|
||||
interface TestData {
|
||||
source: LanguageEqualData;
|
||||
expected: string;
|
||||
}
|
||||
|
||||
const testValues: TestData[] = [
|
||||
{
|
||||
source: {
|
||||
source: {
|
||||
content: {
|
||||
name: "Abkhazian",
|
||||
code2: "ab",
|
||||
code3: "abk",
|
||||
enabled: false,
|
||||
},
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
target: {
|
||||
content: {
|
||||
name: "Aragonese",
|
||||
code2: "an",
|
||||
code3: "arg",
|
||||
enabled: false,
|
||||
},
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
expected: "abk:arg",
|
||||
},
|
||||
{
|
||||
source: {
|
||||
source: {
|
||||
content: {
|
||||
name: "Abkhazian",
|
||||
code2: "ab",
|
||||
code3: "abk",
|
||||
enabled: false,
|
||||
},
|
||||
hi: true,
|
||||
forced: false,
|
||||
},
|
||||
target: {
|
||||
content: {
|
||||
name: "Aragonese",
|
||||
code2: "an",
|
||||
code3: "arg",
|
||||
enabled: false,
|
||||
},
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
expected: "abk@hi:arg",
|
||||
},
|
||||
{
|
||||
source: {
|
||||
source: {
|
||||
content: {
|
||||
name: "Abkhazian",
|
||||
code2: "ab",
|
||||
code3: "abk",
|
||||
enabled: false,
|
||||
},
|
||||
hi: false,
|
||||
forced: true,
|
||||
},
|
||||
target: {
|
||||
content: {
|
||||
name: "Aragonese",
|
||||
code2: "an",
|
||||
code3: "arg",
|
||||
enabled: false,
|
||||
},
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
expected: "abk@forced:arg",
|
||||
},
|
||||
];
|
||||
|
||||
function testEncodeResult({ source, expected }: TestData) {
|
||||
const encoded = encodeEqualData(source);
|
||||
|
||||
expect(
|
||||
encoded,
|
||||
`Encoded result '${encoded}' is not matched to '${expected}'`
|
||||
).toEqual(expected);
|
||||
}
|
||||
|
||||
testValues.forEach(testEncodeResult);
|
||||
});
|
||||
});
|
@ -0,0 +1,365 @@
|
||||
import { useLanguages } from "@/apis/hooks";
|
||||
import { Action, SimpleTable } from "@/components";
|
||||
import LanguageSelector from "@/components/bazarr/LanguageSelector";
|
||||
import { languageEqualsKey } from "@/pages/Settings/keys";
|
||||
import { useFormActions } from "@/pages/Settings/utilities/FormValues";
|
||||
import { useSettingValue } from "@/pages/Settings/utilities/hooks";
|
||||
import { LOG } from "@/utilities/console";
|
||||
import { faEquals, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button, Checkbox } from "@mantine/core";
|
||||
import { FunctionComponent, useCallback, useMemo } from "react";
|
||||
import { Column } from "react-table";
|
||||
|
||||
interface GenericEqualTarget<T> {
|
||||
content: T;
|
||||
hi: boolean;
|
||||
forced: boolean;
|
||||
}
|
||||
|
||||
interface LanguageEqualGenericData<T> {
|
||||
source: GenericEqualTarget<T>;
|
||||
target: GenericEqualTarget<T>;
|
||||
}
|
||||
|
||||
export type LanguageEqualImmediateData =
|
||||
LanguageEqualGenericData<Language.CodeType>;
|
||||
|
||||
export type LanguageEqualData = LanguageEqualGenericData<Language.Server>;
|
||||
|
||||
function decodeEqualTarget(
|
||||
text: string
|
||||
): GenericEqualTarget<Language.CodeType> | undefined {
|
||||
const [code, decoration] = text.split("@");
|
||||
|
||||
if (code.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const forced = decoration === "forced";
|
||||
const hi = decoration === "hi";
|
||||
|
||||
return {
|
||||
content: code,
|
||||
forced,
|
||||
hi,
|
||||
};
|
||||
}
|
||||
|
||||
export function decodeEqualData(
|
||||
text: string
|
||||
): LanguageEqualImmediateData | undefined {
|
||||
const [first, second] = text.split(":");
|
||||
|
||||
const source = decodeEqualTarget(first);
|
||||
const target = decodeEqualTarget(second);
|
||||
|
||||
if (source === undefined || target === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
source,
|
||||
target,
|
||||
};
|
||||
}
|
||||
|
||||
function encodeEqualTarget(data: GenericEqualTarget<Language.Server>): string {
|
||||
let text = data.content.code3;
|
||||
if (data.hi) {
|
||||
text += "@hi";
|
||||
} else if (data.forced) {
|
||||
text += "@forced";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
export function encodeEqualData(data: LanguageEqualData): string {
|
||||
const source = encodeEqualTarget(data.source);
|
||||
const target = encodeEqualTarget(data.target);
|
||||
|
||||
return `${source}:${target}`;
|
||||
}
|
||||
|
||||
export function useLatestLanguageEquals(): LanguageEqualData[] {
|
||||
const { data } = useLanguages();
|
||||
|
||||
const latest = useSettingValue<string[]>(languageEqualsKey);
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
latest
|
||||
?.map(decodeEqualData)
|
||||
.map((parsed) => {
|
||||
if (parsed === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const source = data?.find(
|
||||
(value) => value.code3 === parsed.source.content
|
||||
);
|
||||
const target = data?.find(
|
||||
(value) => value.code3 === parsed.target.content
|
||||
);
|
||||
|
||||
if (source === undefined || target === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
source: { ...parsed.source, content: source },
|
||||
target: { ...parsed.target, content: target },
|
||||
};
|
||||
})
|
||||
.filter((v): v is LanguageEqualData => v !== undefined) ?? [],
|
||||
[data, latest]
|
||||
);
|
||||
}
|
||||
|
||||
interface EqualsTableProps {}
|
||||
|
||||
const EqualsTable: FunctionComponent<EqualsTableProps> = () => {
|
||||
const { data: languages } = useLanguages();
|
||||
const canAdd = languages !== undefined;
|
||||
|
||||
const equals = useLatestLanguageEquals();
|
||||
|
||||
const { setValue } = useFormActions();
|
||||
|
||||
const setEquals = useCallback(
|
||||
(values: LanguageEqualData[]) => {
|
||||
const encodedValues = values.map(encodeEqualData);
|
||||
|
||||
LOG("info", "updating language equals data", values);
|
||||
setValue(encodedValues, languageEqualsKey);
|
||||
},
|
||||
[setValue]
|
||||
);
|
||||
|
||||
const add = useCallback(() => {
|
||||
if (languages === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const enabled = languages.find((value) => value.enabled);
|
||||
|
||||
if (enabled === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newValue: LanguageEqualData[] = [
|
||||
...equals,
|
||||
{
|
||||
source: {
|
||||
content: enabled,
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
target: {
|
||||
content: enabled,
|
||||
hi: false,
|
||||
forced: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
setEquals(newValue);
|
||||
}, [equals, languages, setEquals]);
|
||||
|
||||
const update = useCallback(
|
||||
(index: number, value: LanguageEqualData) => {
|
||||
if (index < 0 || index >= equals.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newValue: LanguageEqualData[] = [...equals];
|
||||
|
||||
newValue[index] = { ...value };
|
||||
setEquals(newValue);
|
||||
},
|
||||
[equals, setEquals]
|
||||
);
|
||||
|
||||
const remove = useCallback(
|
||||
(index: number) => {
|
||||
if (index < 0 || index >= equals.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newValue: LanguageEqualData[] = [...equals];
|
||||
|
||||
newValue.splice(index, 1);
|
||||
|
||||
setEquals(newValue);
|
||||
},
|
||||
[equals, setEquals]
|
||||
);
|
||||
|
||||
const columns = useMemo<Column<LanguageEqualData>[]>(
|
||||
() => [
|
||||
{
|
||||
Header: "Source",
|
||||
id: "source-lang",
|
||||
accessor: "source",
|
||||
Cell: ({ value: { content }, row }) => {
|
||||
return (
|
||||
<LanguageSelector
|
||||
enabled
|
||||
value={content}
|
||||
onChange={(result) => {
|
||||
if (result !== null) {
|
||||
update(row.index, {
|
||||
...row.original,
|
||||
source: { ...row.original.source, content: result },
|
||||
});
|
||||
}
|
||||
}}
|
||||
></LanguageSelector>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "source-hi",
|
||||
accessor: "source",
|
||||
Cell: ({ value: { hi }, row }) => {
|
||||
return (
|
||||
<Checkbox
|
||||
label="HI"
|
||||
checked={hi}
|
||||
onChange={({ currentTarget: { checked } }) => {
|
||||
update(row.index, {
|
||||
...row.original,
|
||||
source: {
|
||||
...row.original.source,
|
||||
hi: checked,
|
||||
forced: checked ? false : row.original.source.forced,
|
||||
},
|
||||
});
|
||||
}}
|
||||
></Checkbox>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "source-forced",
|
||||
accessor: "source",
|
||||
Cell: ({ value: { forced }, row }) => {
|
||||
return (
|
||||
<Checkbox
|
||||
label="Forced"
|
||||
checked={forced}
|
||||
onChange={({ currentTarget: { checked } }) => {
|
||||
update(row.index, {
|
||||
...row.original,
|
||||
source: {
|
||||
...row.original.source,
|
||||
forced: checked,
|
||||
hi: checked ? false : row.original.source.hi,
|
||||
},
|
||||
});
|
||||
}}
|
||||
></Checkbox>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "equal-icon",
|
||||
Cell: () => {
|
||||
return <FontAwesomeIcon icon={faEquals} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "Target",
|
||||
id: "target-lang",
|
||||
accessor: "target",
|
||||
Cell: ({ value: { content }, row }) => {
|
||||
return (
|
||||
<LanguageSelector
|
||||
enabled
|
||||
value={content}
|
||||
onChange={(result) => {
|
||||
if (result !== null) {
|
||||
update(row.index, {
|
||||
...row.original,
|
||||
target: { ...row.original.target, content: result },
|
||||
});
|
||||
}
|
||||
}}
|
||||
></LanguageSelector>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "target-hi",
|
||||
accessor: "target",
|
||||
Cell: ({ value: { hi }, row }) => {
|
||||
return (
|
||||
<Checkbox
|
||||
label="HI"
|
||||
checked={hi}
|
||||
onChange={({ currentTarget: { checked } }) => {
|
||||
update(row.index, {
|
||||
...row.original,
|
||||
target: {
|
||||
...row.original.target,
|
||||
hi: checked,
|
||||
forced: checked ? false : row.original.target.forced,
|
||||
},
|
||||
});
|
||||
}}
|
||||
></Checkbox>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "target-forced",
|
||||
accessor: "target",
|
||||
Cell: ({ value: { forced }, row }) => {
|
||||
return (
|
||||
<Checkbox
|
||||
label="Forced"
|
||||
checked={forced}
|
||||
onChange={({ currentTarget: { checked } }) => {
|
||||
update(row.index, {
|
||||
...row.original,
|
||||
target: {
|
||||
...row.original.target,
|
||||
forced: checked,
|
||||
hi: checked ? false : row.original.target.hi,
|
||||
},
|
||||
});
|
||||
}}
|
||||
></Checkbox>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "action",
|
||||
accessor: "target",
|
||||
Cell: ({ row }) => {
|
||||
return (
|
||||
<Action
|
||||
label="Remove"
|
||||
icon={faTrash}
|
||||
color="red"
|
||||
onClick={() => remove(row.index)}
|
||||
></Action>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
[remove, update]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SimpleTable data={equals} columns={columns}></SimpleTable>
|
||||
<Button fullWidth disabled={!canAdd} color="light" onClick={add}>
|
||||
{canAdd ? "Add Equal" : "No Enabled Languages"}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default EqualsTable;
|
@ -1,45 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import inspect
|
||||
|
||||
from bazarr.app import get_providers
|
||||
|
||||
|
||||
def test_get_providers_auth():
|
||||
for val in get_providers.get_providers_auth().values():
|
||||
assert isinstance(val, dict)
|
||||
|
||||
|
||||
def test_get_providers_auth_with_provider_registry():
|
||||
"""Make sure all providers will be properly initialized with bazarr
|
||||
configs"""
|
||||
from subliminal_patch.extensions import provider_registry
|
||||
|
||||
auths = get_providers.get_providers_auth()
|
||||
for key, val in auths.items():
|
||||
provider = provider_registry[key]
|
||||
sign = inspect.signature(provider.__init__)
|
||||
for sub_key in val.keys():
|
||||
if sub_key not in sign.parameters:
|
||||
raise ValueError(f"'{sub_key}' parameter not present in {provider}")
|
||||
|
||||
assert sign.parameters[sub_key] is not None
|
||||
|
||||
|
||||
def test_get_providers_auth_embeddedsubtitles():
|
||||
item = get_providers.get_providers_auth()["embeddedsubtitles"]
|
||||
assert isinstance(item["included_codecs"], list)
|
||||
assert isinstance(item["hi_fallback"], bool)
|
||||
assert isinstance(item["cache_dir"], str)
|
||||
assert isinstance(item["ffprobe_path"], str)
|
||||
assert isinstance(item["ffmpeg_path"], str)
|
||||
assert isinstance(item["timeout"], str)
|
||||
assert isinstance(item["unknown_as_english"], bool)
|
||||
|
||||
|
||||
def test_get_providers_auth_karagarga():
|
||||
item = get_providers.get_providers_auth()["karagarga"]
|
||||
assert item["username"] is not None
|
||||
assert item["password"] is not None
|
||||
assert item["f_username"] is not None
|
||||
assert item["f_password"] is not None
|
@ -0,0 +1,115 @@
|
||||
import inspect
|
||||
|
||||
import pytest
|
||||
from subliminal_patch.core import Language
|
||||
|
||||
from bazarr.app import get_providers
|
||||
|
||||
|
||||
def test_get_providers_auth():
|
||||
for val in get_providers.get_providers_auth().values():
|
||||
assert isinstance(val, dict)
|
||||
|
||||
|
||||
def test_get_providers_auth_with_provider_registry():
|
||||
"""Make sure all providers will be properly initialized with bazarr
|
||||
configs"""
|
||||
from subliminal_patch.extensions import provider_registry
|
||||
|
||||
auths = get_providers.get_providers_auth()
|
||||
for key, val in auths.items():
|
||||
provider = provider_registry[key]
|
||||
sign = inspect.signature(provider.__init__)
|
||||
for sub_key in val.keys():
|
||||
if sub_key not in sign.parameters:
|
||||
raise ValueError(f"'{sub_key}' parameter not present in {provider}")
|
||||
|
||||
assert sign.parameters[sub_key] is not None
|
||||
|
||||
|
||||
def test_get_providers_auth_embeddedsubtitles():
|
||||
item = get_providers.get_providers_auth()["embeddedsubtitles"]
|
||||
assert isinstance(item["included_codecs"], list)
|
||||
assert isinstance(item["hi_fallback"], bool)
|
||||
assert isinstance(item["cache_dir"], str)
|
||||
assert isinstance(item["ffprobe_path"], str)
|
||||
assert isinstance(item["ffmpeg_path"], str)
|
||||
assert isinstance(item["timeout"], str)
|
||||
assert isinstance(item["unknown_as_english"], bool)
|
||||
|
||||
|
||||
def test_get_providers_auth_karagarga():
|
||||
item = get_providers.get_providers_auth()["karagarga"]
|
||||
assert item["username"] is not None
|
||||
assert item["password"] is not None
|
||||
assert item["f_username"] is not None
|
||||
assert item["f_password"] is not None
|
||||
|
||||
|
||||
def test_get_language_equals_default_settings():
|
||||
assert isinstance(get_providers.get_language_equals(), list)
|
||||
|
||||
|
||||
def test_get_language_equals_injected_settings_invalid():
|
||||
config = get_providers.settings
|
||||
config.set("general", "language_equals", '["invalid"]')
|
||||
assert not get_providers.get_language_equals(config)
|
||||
|
||||
|
||||
def test_get_language_equals_injected_settings_valid():
|
||||
config = get_providers.settings
|
||||
config.set("general", "language_equals", '["spa:spa-MX"]')
|
||||
|
||||
result = get_providers.get_language_equals(config)
|
||||
assert result == [(Language("spa"), Language("spa", "MX"))]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"config_value,expected",
|
||||
[
|
||||
('["spa:spl"]', (Language("spa"), Language("spa", "MX"))),
|
||||
('["por:pob"]', (Language("por"), Language("por", "BR"))),
|
||||
('["zho:zht"]', (Language("zho"), Language("zho", "TW"))),
|
||||
],
|
||||
)
|
||||
def test_get_language_equals_injected_settings_custom_lang_alpha3(
|
||||
config_value, expected
|
||||
):
|
||||
config = get_providers.settings
|
||||
|
||||
config.set("general", "language_equals", config_value)
|
||||
|
||||
result = get_providers.get_language_equals(config)
|
||||
assert result == [expected]
|
||||
|
||||
|
||||
def test_get_language_equals_injected_settings_multiple():
|
||||
config = get_providers.settings
|
||||
|
||||
config.set(
|
||||
"general",
|
||||
"language_equals",
|
||||
"['eng@hi:eng', 'spa:spl', 'spa@hi:spl', 'spl@hi:spl']",
|
||||
)
|
||||
|
||||
result = get_providers.get_language_equals(config)
|
||||
assert len(result) == 4
|
||||
|
||||
|
||||
def test_get_language_equals_injected_settings_valid_multiple():
|
||||
config = get_providers.settings
|
||||
config.set("general", "language_equals", '["spa:spa-MX", "spa-MX:spa"]')
|
||||
|
||||
result = get_providers.get_language_equals(config)
|
||||
assert result == [
|
||||
(Language("spa"), Language("spa", "MX")),
|
||||
(Language("spa", "MX"), Language("spa")),
|
||||
]
|
||||
|
||||
|
||||
def test_get_language_equals_injected_settings_hi():
|
||||
config = get_providers.settings
|
||||
config.set("general", "language_equals", '["eng@hi:eng"]')
|
||||
|
||||
result = get_providers.get_language_equals(config)
|
||||
assert result == [(Language("eng", hi=True), Language("eng"))]
|
@ -0,0 +1,10 @@
|
||||
from bazarr.subtitles import pool
|
||||
|
||||
|
||||
def test_init_pool():
|
||||
assert pool._init_pool("movie")
|
||||
|
||||
|
||||
def test_pool_update():
|
||||
pool_ = pool._init_pool("movie")
|
||||
assert pool._pool_update(pool_, "movie")
|
Loading…
Reference in new issue