feat(product-suite): confirm prior successful generations
This commit is contained in:
@@ -867,12 +867,48 @@ class ImageStudioTests(TempDirMixin, unittest.TestCase):
|
||||
image_studio.ASSET_KIND_ORIGINAL,
|
||||
path=db_path,
|
||||
)
|
||||
other_source = image_studio.add_asset(
|
||||
other_project.id,
|
||||
image_studio.ASSET_KIND_ORIGINAL,
|
||||
path=db_path,
|
||||
)
|
||||
other_first = image_studio.create_job(
|
||||
other_project.id,
|
||||
source_asset_id=other_source.id,
|
||||
task_key="other-first-generation-round",
|
||||
generation_round_key="other-failed-round",
|
||||
generation_slot_index=0,
|
||||
path=db_path,
|
||||
)
|
||||
image_studio.update_job_status(
|
||||
other_first.id,
|
||||
"succeeded",
|
||||
path=db_path,
|
||||
)
|
||||
other_failed = image_studio.create_job(
|
||||
other_project.id,
|
||||
source_asset_id=other_source.id,
|
||||
task_key="other-failed-generation-round",
|
||||
generation_round_key="other-failed-round",
|
||||
generation_slot_index=0,
|
||||
path=db_path,
|
||||
)
|
||||
image_studio.update_job_status(
|
||||
other_failed.id,
|
||||
"failed",
|
||||
path=db_path,
|
||||
)
|
||||
legacy = image_studio.create_job(
|
||||
project.id,
|
||||
source_asset_id=source.id,
|
||||
task_key="legacy-generation-round",
|
||||
path=db_path,
|
||||
)
|
||||
legacy = image_studio.update_job_status(
|
||||
legacy.id,
|
||||
"succeeded",
|
||||
path=db_path,
|
||||
)
|
||||
round_one = "round-one"
|
||||
first = image_studio.create_job(
|
||||
project.id,
|
||||
@@ -1026,6 +1062,21 @@ class ImageStudioTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertEqual(1, summary.failed_count)
|
||||
self.assertTrue(rounds[-1].is_legacy)
|
||||
|
||||
success_summary = image_studio.get_successful_generation_history_summary(
|
||||
project.id,
|
||||
path=db_path,
|
||||
)
|
||||
self.assertEqual(project.id, success_summary.project_id)
|
||||
self.assertEqual(2, success_summary.successful_round_count)
|
||||
self.assertEqual(3, success_summary.successful_image_count)
|
||||
self.assertTrue(success_summary.latest_succeeded_at)
|
||||
other_summary = image_studio.get_successful_generation_history_summary(
|
||||
other_project.id,
|
||||
path=db_path,
|
||||
)
|
||||
self.assertEqual(0, other_summary.successful_round_count)
|
||||
self.assertEqual(0, other_summary.successful_image_count)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_global_generation_rounds_filter_paginate_and_exclude_deleted_projects(self):
|
||||
|
||||
@@ -2118,9 +2118,18 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertIsInstance(dialog, ProductSuiteGlobalHistoryDialog)
|
||||
self.assertEqual(project.id, dialog.current_project_id)
|
||||
self.assertTrue(dialog.isVisible())
|
||||
self.assertFalse(dialog.current_project_checkbox.isChecked())
|
||||
|
||||
tab.open_history_dialog(
|
||||
current_project_only=True,
|
||||
current_project_id=project.id,
|
||||
)
|
||||
self.app.processEvents()
|
||||
self.assertTrue(dialog.current_project_checkbox.isChecked())
|
||||
|
||||
tab.open_history_dialog()
|
||||
self.assertIs(dialog, tab._history_dialog)
|
||||
self.assertFalse(dialog.current_project_checkbox.isChecked())
|
||||
tab.close_task(0)
|
||||
self.app.processEvents()
|
||||
self.assertIs(dialog, tab._history_dialog)
|
||||
@@ -2924,6 +2933,135 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_successful_history_requires_decision_before_new_generation(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
config = self._config(temp_dir)
|
||||
account = accounts.create_account(
|
||||
"主店",
|
||||
"alias-a",
|
||||
debug_port=9222,
|
||||
config=config,
|
||||
)
|
||||
project = image_studio.create_or_get_project(
|
||||
account,
|
||||
item_id="51100639510",
|
||||
path=config["db_path"],
|
||||
)
|
||||
source_path = os.path.join(temp_dir, "source.png")
|
||||
self._write_image(source_path)
|
||||
source = image_studio.add_asset(
|
||||
project.id,
|
||||
image_studio.ASSET_KIND_ORIGINAL,
|
||||
local_path=source_path,
|
||||
path=config["db_path"],
|
||||
)
|
||||
history_job = image_studio.create_job(
|
||||
project.id,
|
||||
source_asset_id=source.id,
|
||||
job_type="场景图",
|
||||
prompt="已有成功历史",
|
||||
generation_round_key="history-round",
|
||||
generation_slot_index=0,
|
||||
path=config["db_path"],
|
||||
)
|
||||
image_studio.update_job_status(
|
||||
history_job.id,
|
||||
"succeeded",
|
||||
path=config["db_path"],
|
||||
)
|
||||
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
|
||||
self.addCleanup(tab.close)
|
||||
state = tab._displayed_state
|
||||
state.account_alias = "alias-a"
|
||||
state.item_id = project.item_id
|
||||
state.project_id = project.id
|
||||
state.project_binding_state = project.binding_state
|
||||
state.prompt = "轻便耐用,适合日常使用"
|
||||
tab._load_state(state)
|
||||
|
||||
history_confirmations = []
|
||||
cost_confirmations = []
|
||||
tab._confirm_new_generation_history = (
|
||||
lambda _state, summary: history_confirmations.append(summary) or "cancel"
|
||||
)
|
||||
tab._confirm = lambda title, message, **kwargs: cost_confirmations.append(
|
||||
(title, message, kwargs)
|
||||
) and False
|
||||
|
||||
self.assertFalse(tab.start_generation(state))
|
||||
self.assertEqual(1, len(history_confirmations))
|
||||
self.assertEqual(1, history_confirmations[0].successful_round_count)
|
||||
self.assertEqual(1, history_confirmations[0].successful_image_count)
|
||||
self.assertEqual([], cost_confirmations)
|
||||
self.assertEqual(
|
||||
[history_job.id],
|
||||
[job.id for job in image_studio.list_jobs(project.id, path=config["db_path"])],
|
||||
)
|
||||
|
||||
tab._confirm_new_generation_history = lambda _state, _summary: "history"
|
||||
tab.open_history_dialog = mock.Mock()
|
||||
self.assertFalse(tab.start_generation(state))
|
||||
tab.open_history_dialog.assert_called_once_with(
|
||||
current_project_only=True,
|
||||
current_project_id=project.id,
|
||||
)
|
||||
self.assertEqual([], cost_confirmations)
|
||||
|
||||
tab._confirm_new_generation_history = lambda _state, _summary: "continue"
|
||||
tab._confirm = lambda title, message, **kwargs: cost_confirmations.append(
|
||||
(title, message, kwargs)
|
||||
) or True
|
||||
with mock.patch.object(tab, "_start_thread", return_value=mock.Mock()):
|
||||
self.assertTrue(tab.start_generation(state))
|
||||
self.assertEqual(1, len(cost_confirmations))
|
||||
self.assertEqual("确认生成商品套图", cost_confirmations[0][0])
|
||||
self.assertNotEqual("history-round", state.generation_round_key)
|
||||
self.assertTrue(state.generation_round_key)
|
||||
state.worker = None
|
||||
state.thread = None
|
||||
state.generation_run_token = ""
|
||||
tab._generation_run_states.clear()
|
||||
|
||||
failed_job = image_studio.create_job(
|
||||
project.id,
|
||||
source_asset_id=source.id,
|
||||
job_type="场景图",
|
||||
prompt="失败重试",
|
||||
generation_round_key="retry-round",
|
||||
generation_slot_index=0,
|
||||
path=config["db_path"],
|
||||
)
|
||||
failed_job = image_studio.update_job_status(
|
||||
failed_job.id,
|
||||
"failed",
|
||||
path=config["db_path"],
|
||||
)
|
||||
history_decision = mock.Mock(return_value="cancel")
|
||||
tab._confirm_new_generation_history = history_decision
|
||||
tab._confirm = mock.Mock(return_value=True)
|
||||
with mock.patch.object(tab, "_start_thread", return_value=mock.Mock()):
|
||||
self.assertTrue(
|
||||
tab.start_generation(
|
||||
state,
|
||||
specs=[
|
||||
{
|
||||
"source_asset_id": source.id,
|
||||
"job_type": failed_job.job_type,
|
||||
"prompt": failed_job.prompt,
|
||||
}
|
||||
],
|
||||
retry_job_id=failed_job.id,
|
||||
)
|
||||
)
|
||||
history_decision.assert_not_called()
|
||||
tab._confirm.assert_not_called()
|
||||
state.worker = None
|
||||
state.thread = None
|
||||
state.generation_run_token = ""
|
||||
tab._generation_run_states.clear()
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_original_checkbox_click_and_keyboard_delete_keep_actions_separate(self):
|
||||
original_list = ProductOriginalList()
|
||||
self.addCleanup(original_list.close)
|
||||
|
||||
Reference in New Issue
Block a user