feat(backend): drop dictionary dialect columns, add allowed_languages
- Removes source_dialect and target_dialect from TerminologyDictionary model, schemas, routes, helper serialization, and all tests - Adds allowed_languages config field (BCP-47 language codes) to GlobalSettings with validation, consolidated settings response, and API endpoint - Adds alembic migration f1a2b3c4d5e6 to drop the two columns
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
"""drop source_dialect/target_dialect from terminology_dictionaries
|
||||||
|
|
||||||
|
Revision ID: f1a2b3c4d5e6
|
||||||
|
Revises: dabc97097e0e
|
||||||
|
Create Date: 2026-06-02 12:00:00.000000
|
||||||
|
|
||||||
|
"""
|
||||||
|
from collections.abc import Sequence
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
from sqlalchemy import inspect
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = 'f1a2b3c4d5e6'
|
||||||
|
down_revision: str | Sequence[str] | None = 'dabc97097e0e'
|
||||||
|
branch_labels: str | Sequence[str] | None = None
|
||||||
|
depends_on: str | Sequence[str] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def _column_exists(table_name: str, column_name: str) -> bool:
|
||||||
|
conn = op.get_bind()
|
||||||
|
inspector = inspect(conn)
|
||||||
|
columns = [c["name"] for c in inspector.get_columns(table_name)]
|
||||||
|
return column_name in columns
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
"""Drop source_dialect and target_dialect from terminology_dictionaries."""
|
||||||
|
if not _column_exists("terminology_dictionaries", "source_dialect"):
|
||||||
|
return
|
||||||
|
op.drop_column("terminology_dictionaries", "source_dialect")
|
||||||
|
op.drop_column("terminology_dictionaries", "target_dialect")
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Re-add source_dialect and target_dialect to terminology_dictionaries."""
|
||||||
|
import sqlalchemy as sa
|
||||||
|
op.add_column("terminology_dictionaries", sa.Column(
|
||||||
|
"source_dialect", sa.String(), nullable=False, server_default="",
|
||||||
|
))
|
||||||
|
op.add_column("terminology_dictionaries", sa.Column(
|
||||||
|
"target_dialect", sa.String(), nullable=False, server_default="",
|
||||||
|
))
|
||||||
@@ -128,6 +128,22 @@ async def get_features(
|
|||||||
# #endregion get_features
|
# #endregion get_features
|
||||||
|
|
||||||
|
|
||||||
|
# #region get_allowed_languages [C:1] [TYPE Function]
|
||||||
|
# @BRIEF Public endpoint returning allowed translation languages for language dropdowns.
|
||||||
|
# @RATIONALE No auth required — needed by dictionary page, job config, etc. everywhere
|
||||||
|
# language selects appear. Non-admin users still need the list.
|
||||||
|
# @PRE Config manager is available.
|
||||||
|
# @POST Returns list of BCP-47 language codes.
|
||||||
|
@router.get("/allowed-languages")
|
||||||
|
async def get_allowed_languages(
|
||||||
|
config_manager: ConfigManager = Depends(get_config_manager),
|
||||||
|
):
|
||||||
|
return config_manager.get_config().settings.allowed_languages
|
||||||
|
|
||||||
|
|
||||||
|
# #endregion get_allowed_languages
|
||||||
|
|
||||||
|
|
||||||
# #region update_global_settings [C:2] [TYPE Function]
|
# #region update_global_settings [C:2] [TYPE Function]
|
||||||
# @BRIEF Updates global application settings.
|
# @BRIEF Updates global application settings.
|
||||||
# @PRE New settings are provided.
|
# @PRE New settings are provided.
|
||||||
@@ -394,6 +410,7 @@ class ConsolidatedSettingsResponse(BaseModel):
|
|||||||
notifications: dict = {}
|
notifications: dict = {}
|
||||||
features: dict = {}
|
features: dict = {}
|
||||||
app_timezone: str = "Europe/Moscow"
|
app_timezone: str = "Europe/Moscow"
|
||||||
|
allowed_languages: list[str] = []
|
||||||
|
|
||||||
|
|
||||||
# #endregion ConsolidatedSettingsResponse
|
# #endregion ConsolidatedSettingsResponse
|
||||||
@@ -465,6 +482,7 @@ async def get_consolidated_settings(
|
|||||||
notifications=notifications_payload,
|
notifications=notifications_payload,
|
||||||
features=config.settings.features.model_dump(),
|
features=config.settings.features.model_dump(),
|
||||||
app_timezone=config.settings.app_timezone,
|
app_timezone=config.settings.app_timezone,
|
||||||
|
allowed_languages=config.settings.allowed_languages,
|
||||||
)
|
)
|
||||||
logger.reflect(
|
logger.reflect(
|
||||||
"Consolidated settings payload assembled",
|
"Consolidated settings payload assembled",
|
||||||
@@ -537,6 +555,10 @@ async def update_consolidated_settings(
|
|||||||
current_settings.app_timezone = new_tz
|
current_settings.app_timezone = new_tz
|
||||||
invalidate_timezone_cache()
|
invalidate_timezone_cache()
|
||||||
|
|
||||||
|
# Update allowed_languages if provided
|
||||||
|
if "allowed_languages" in settings_patch:
|
||||||
|
current_settings.allowed_languages = settings_patch["allowed_languages"]
|
||||||
|
|
||||||
config_manager.update_global_settings(current_settings)
|
config_manager.update_global_settings(current_settings)
|
||||||
return {"status": "success", "message": "Settings updated"}
|
return {"status": "success", "message": "Settings updated"}
|
||||||
|
|
||||||
|
|||||||
@@ -88,8 +88,6 @@ async def create_dictionary(
|
|||||||
d = DictionaryManager.create_dictionary(
|
d = DictionaryManager.create_dictionary(
|
||||||
db,
|
db,
|
||||||
name=payload.name,
|
name=payload.name,
|
||||||
source_dialect=payload.source_dialect,
|
|
||||||
target_dialect=payload.target_dialect,
|
|
||||||
created_by=current_user.username,
|
created_by=current_user.username,
|
||||||
description=payload.description,
|
description=payload.description,
|
||||||
is_active=payload.is_active,
|
is_active=payload.is_active,
|
||||||
@@ -120,8 +118,6 @@ async def update_dictionary(
|
|||||||
dict_id=dictionary_id,
|
dict_id=dictionary_id,
|
||||||
name=payload.name,
|
name=payload.name,
|
||||||
description=payload.description,
|
description=payload.description,
|
||||||
source_dialect=payload.source_dialect,
|
|
||||||
target_dialect=payload.target_dialect,
|
|
||||||
is_active=payload.is_active,
|
is_active=payload.is_active,
|
||||||
)
|
)
|
||||||
from ....models.translate import DictionaryEntry
|
from ....models.translate import DictionaryEntry
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ def _dict_to_response(d: Any, entry_count: int = 0) -> dict:
|
|||||||
"id": d.id,
|
"id": d.id,
|
||||||
"name": d.name,
|
"name": d.name,
|
||||||
"description": d.description,
|
"description": d.description,
|
||||||
"source_dialect": d.source_dialect,
|
|
||||||
"target_dialect": d.target_dialect,
|
|
||||||
"is_active": d.is_active,
|
"is_active": d.is_active,
|
||||||
"created_by": d.created_by,
|
"created_by": d.created_by,
|
||||||
"created_at": d.created_at,
|
"created_at": d.created_at,
|
||||||
|
|||||||
@@ -141,6 +141,26 @@ class GlobalSettings(BaseModel):
|
|||||||
# Global worker limit for concurrent validation runs
|
# Global worker limit for concurrent validation runs
|
||||||
GLOBAL_VALIDATION_WORKER_LIMIT: int = 3
|
GLOBAL_VALIDATION_WORKER_LIMIT: int = 3
|
||||||
|
|
||||||
|
# Allowed languages for translation (BCP-47 codes)
|
||||||
|
allowed_languages: list[str] = Field(
|
||||||
|
default_factory=lambda: [
|
||||||
|
"ru", "en", "de", "fr", "es", "it", "pt", "zh", "ja", "ko",
|
||||||
|
"ar", "tr", "nl", "pl", "sv", "da", "fi", "cs", "hu", "ro",
|
||||||
|
"vi", "th", "he", "id", "ms",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
@field_validator("allowed_languages")
|
||||||
|
@classmethod
|
||||||
|
def validate_allowed_languages(cls, v: list[str]) -> list[str]:
|
||||||
|
import re
|
||||||
|
for tag in v:
|
||||||
|
if not tag or not tag.strip():
|
||||||
|
raise ValueError("Empty language code is not allowed")
|
||||||
|
if not re.match(r'^[a-zA-Z]{2,8}(-[a-zA-Z0-9]{1,8})*$', tag.strip()):
|
||||||
|
raise ValueError(f"Invalid BCP-47 language code: {tag}")
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
# #endregion GlobalSettings
|
# #endregion GlobalSettings
|
||||||
|
|
||||||
|
|||||||
@@ -205,8 +205,6 @@ class TerminologyDictionary(Base):
|
|||||||
id = Column(String, primary_key=True, default=generate_uuid)
|
id = Column(String, primary_key=True, default=generate_uuid)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
description = Column(Text, nullable=True)
|
description = Column(Text, nullable=True)
|
||||||
source_dialect = Column(String, nullable=False)
|
|
||||||
target_dialect = Column(String, nullable=False)
|
|
||||||
is_active = Column(Boolean, default=True)
|
is_active = Column(Boolean, default=True)
|
||||||
created_by = Column(String, nullable=True)
|
created_by = Column(String, nullable=True)
|
||||||
created_at = Column(DateTime, default=lambda: datetime.now(UTC))
|
created_at = Column(DateTime, default=lambda: datetime.now(UTC))
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ def _create_dict(db_session, name="Test Dict") -> TerminologyDictionary:
|
|||||||
d = TerminologyDictionary(
|
d = TerminologyDictionary(
|
||||||
id=str(uuid.uuid4()),
|
id=str(uuid.uuid4()),
|
||||||
name=name,
|
name=name,
|
||||||
source_dialect="ru",
|
|
||||||
target_dialect="en",
|
|
||||||
)
|
)
|
||||||
db_session.add(d)
|
db_session.add(d)
|
||||||
db_session.flush()
|
db_session.flush()
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class TestContextCapture:
|
|||||||
|
|
||||||
# region test_context_capture_in_correction [C:2] [TYPE Function]
|
# region test_context_capture_in_correction [C:2] [TYPE Function]
|
||||||
def test_context_capture_in_correction(self, db_session: Session):
|
def test_context_capture_in_correction(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test Dict", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test Dict")
|
||||||
job = TranslationJob(name="Ctx Job", source_dialect="a", target_dialect="b", status="DRAFT")
|
job = TranslationJob(name="Ctx Job", source_dialect="a", target_dialect="b", status="DRAFT")
|
||||||
db_session.add(job)
|
db_session.add(job)
|
||||||
db_session.flush()
|
db_session.flush()
|
||||||
|
|||||||
@@ -46,13 +46,10 @@ class TestDictionaryCRUD:
|
|||||||
def test_create_dictionary(self, db_session: Session):
|
def test_create_dictionary(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(
|
d = DictionaryManager.create_dictionary(
|
||||||
db_session, name="Finance Terms",
|
db_session, name="Finance Terms",
|
||||||
source_dialect="postgresql", target_dialect="clickhouse",
|
|
||||||
created_by="test_user", description="Finance-related term mappings",
|
created_by="test_user", description="Finance-related term mappings",
|
||||||
)
|
)
|
||||||
assert d.id is not None
|
assert d.id is not None
|
||||||
assert d.name == "Finance Terms"
|
assert d.name == "Finance Terms"
|
||||||
assert d.source_dialect == "postgresql"
|
|
||||||
assert d.target_dialect == "clickhouse"
|
|
||||||
assert d.created_by == "test_user"
|
assert d.created_by == "test_user"
|
||||||
assert d.is_active is True
|
assert d.is_active is True
|
||||||
|
|
||||||
@@ -64,7 +61,7 @@ class TestDictionaryCRUD:
|
|||||||
# region test_update_dictionary [C:2] [TYPE Function]
|
# region test_update_dictionary [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify dictionary metadata update.
|
# @BRIEF Verify dictionary metadata update.
|
||||||
def test_update_dictionary(self, db_session: Session):
|
def test_update_dictionary(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Old Name", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Old Name")
|
||||||
updated = DictionaryManager.update_dictionary(
|
updated = DictionaryManager.update_dictionary(
|
||||||
db_session, d.id, name="New Name", description="Updated desc", is_active=False,
|
db_session, d.id, name="New Name", description="Updated desc", is_active=False,
|
||||||
)
|
)
|
||||||
@@ -76,7 +73,7 @@ class TestDictionaryCRUD:
|
|||||||
# region test_delete_dictionary [C:2] [TYPE Function]
|
# region test_delete_dictionary [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify dictionary deletion also removes entries.
|
# @BRIEF Verify dictionary deletion also removes entries.
|
||||||
def test_delete_dictionary(self, db_session: Session):
|
def test_delete_dictionary(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="To Delete", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="To Delete")
|
||||||
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
assert entry.id is not None
|
assert entry.id is not None
|
||||||
DictionaryManager.delete_dictionary(db_session, d.id)
|
DictionaryManager.delete_dictionary(db_session, d.id)
|
||||||
@@ -88,7 +85,7 @@ class TestDictionaryCRUD:
|
|||||||
# @BRIEF Verify paginated dictionary listing.
|
# @BRIEF Verify paginated dictionary listing.
|
||||||
def test_list_dictionaries(self, db_session: Session):
|
def test_list_dictionaries(self, db_session: Session):
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
DictionaryManager.create_dictionary(db_session, name=f"Dict {i}", source_dialect="a", target_dialect="b")
|
DictionaryManager.create_dictionary(db_session, name=f"Dict {i}")
|
||||||
dicts, total = DictionaryManager.list_dictionaries(db_session, page=1, page_size=2)
|
dicts, total = DictionaryManager.list_dictionaries(db_session, page=1, page_size=2)
|
||||||
assert total == 5
|
assert total == 5
|
||||||
assert len(dicts) == 2
|
assert len(dicts) == 2
|
||||||
@@ -97,7 +94,7 @@ class TestDictionaryCRUD:
|
|||||||
# region test_delete_dictionary_blocked_by_active_job [C:2] [TYPE Function]
|
# region test_delete_dictionary_blocked_by_active_job [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify deletion is blocked when attached to active/scheduled jobs.
|
# @BRIEF Verify deletion is blocked when attached to active/scheduled jobs.
|
||||||
def test_delete_dictionary_blocked_by_active_job(self, db_session: Session):
|
def test_delete_dictionary_blocked_by_active_job(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
job = TranslationJob(name="Active Job", source_dialect="a", target_dialect="b", status="ACTIVE", created_by="test_user")
|
job = TranslationJob(name="Active Job", source_dialect="a", target_dialect="b", status="ACTIVE", created_by="test_user")
|
||||||
db_session.add(job)
|
db_session.add(job)
|
||||||
db_session.flush()
|
db_session.flush()
|
||||||
@@ -111,7 +108,7 @@ class TestDictionaryCRUD:
|
|||||||
# region test_delete_dictionary_allowed_with_completed_job [C:2] [TYPE Function]
|
# region test_delete_dictionary_allowed_with_completed_job [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify deletion is allowed when only completed/failed jobs reference the dictionary.
|
# @BRIEF Verify deletion is allowed when only completed/failed jobs reference the dictionary.
|
||||||
def test_delete_dictionary_allowed_with_completed_job(self, db_session: Session):
|
def test_delete_dictionary_allowed_with_completed_job(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
job = TranslationJob(name="Completed Job", source_dialect="a", target_dialect="b", status="COMPLETED", created_by="test_user")
|
job = TranslationJob(name="Completed Job", source_dialect="a", target_dialect="b", status="COMPLETED", created_by="test_user")
|
||||||
db_session.add(job)
|
db_session.add(job)
|
||||||
db_session.flush()
|
db_session.flush()
|
||||||
@@ -130,7 +127,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_add_entry_duplicate [C:2] [TYPE Function]
|
# region test_add_entry_duplicate [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify duplicate entry raises ValueError.
|
# @BRIEF Verify duplicate entry raises ValueError.
|
||||||
def test_add_entry_duplicate(self, db_session: Session):
|
def test_add_entry_duplicate(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "Hello", "Hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "Hello", "Hola", source_language="en", target_language="es")
|
||||||
with pytest.raises(ValueError, match="already exists"):
|
with pytest.raises(ValueError, match="already exists"):
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "Bonjour", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "Bonjour", source_language="en", target_language="es")
|
||||||
@@ -141,8 +138,8 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_add_entry_duplicate_per_dictionary [C:2] [TYPE Function]
|
# region test_add_entry_duplicate_per_dictionary [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify duplicate is per-dictionary (same term in different dicts is OK).
|
# @BRIEF Verify duplicate is per-dictionary (same term in different dicts is OK).
|
||||||
def test_add_entry_duplicate_per_dictionary(self, db_session: Session):
|
def test_add_entry_duplicate_per_dictionary(self, db_session: Session):
|
||||||
d1 = DictionaryManager.create_dictionary(db_session, name="Dict1", source_dialect="a", target_dialect="b")
|
d1 = DictionaryManager.create_dictionary(db_session, name="Dict1")
|
||||||
d2 = DictionaryManager.create_dictionary(db_session, name="Dict2", source_dialect="a", target_dialect="b")
|
d2 = DictionaryManager.create_dictionary(db_session, name="Dict2")
|
||||||
DictionaryManager.add_entry(db_session, d1.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d1.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
entry = DictionaryManager.add_entry(db_session, d2.id, "hello", "bonjour", source_language="en", target_language="es")
|
entry = DictionaryManager.add_entry(db_session, d2.id, "hello", "bonjour", source_language="en", target_language="es")
|
||||||
assert entry.id is not None
|
assert entry.id is not None
|
||||||
@@ -151,7 +148,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_edit_entry [C:2] [TYPE Function]
|
# region test_edit_entry [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify entry edit updates fields and enforces uniqueness.
|
# @BRIEF Verify entry edit updates fields and enforces uniqueness.
|
||||||
def test_edit_entry(self, db_session: Session):
|
def test_edit_entry(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
updated = DictionaryManager.edit_entry(db_session, entry.id, target_term="HOLA!")
|
updated = DictionaryManager.edit_entry(db_session, entry.id, target_term="HOLA!")
|
||||||
assert updated.target_term == "HOLA!"
|
assert updated.target_term == "HOLA!"
|
||||||
@@ -163,7 +160,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_delete_entry [C:2] [TYPE Function]
|
# region test_delete_entry [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify entry deletion.
|
# @BRIEF Verify entry deletion.
|
||||||
def test_delete_entry(self, db_session: Session):
|
def test_delete_entry(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
DictionaryManager.delete_entry(db_session, entry.id)
|
DictionaryManager.delete_entry(db_session, entry.id)
|
||||||
entries, total = DictionaryManager.list_entries(db_session, d.id)
|
entries, total = DictionaryManager.list_entries(db_session, d.id)
|
||||||
@@ -173,7 +170,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_clear_entries [C:2] [TYPE Function]
|
# region test_clear_entries [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify clearing all entries for a dictionary.
|
# @BRIEF Verify clearing all entries for a dictionary.
|
||||||
def test_clear_entries(self, db_session: Session):
|
def test_clear_entries(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "world", "mundo", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "world", "mundo", source_language="en", target_language="es")
|
||||||
deleted = DictionaryManager.clear_entries(db_session, d.id)
|
deleted = DictionaryManager.clear_entries(db_session, d.id)
|
||||||
@@ -185,7 +182,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_add_entry_with_language_pair [C:2] [TYPE Function]
|
# region test_add_entry_with_language_pair [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify creating entry with language pair stores correctly.
|
# @BRIEF Verify creating entry with language pair stores correctly.
|
||||||
def test_add_entry_with_language_pair(self, db_session: Session):
|
def test_add_entry_with_language_pair(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Lang Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Lang Test")
|
||||||
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
entry = DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
||||||
assert entry.source_language == "en"
|
assert entry.source_language == "en"
|
||||||
assert entry.target_language == "ru"
|
assert entry.target_language == "ru"
|
||||||
@@ -198,7 +195,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_duplicate_same_language_pair [C:2] [TYPE Function]
|
# region test_duplicate_same_language_pair [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify duplicate with same language pair raises conflict.
|
# @BRIEF Verify duplicate with same language pair raises conflict.
|
||||||
def test_duplicate_same_language_pair(self, db_session: Session):
|
def test_duplicate_same_language_pair(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Dup Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Dup Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
||||||
with pytest.raises(ValueError, match="already exists"):
|
with pytest.raises(ValueError, match="already exists"):
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="ru")
|
||||||
@@ -207,7 +204,7 @@ class TestDictionaryEntryCRUD:
|
|||||||
# region test_same_term_different_language_pair [C:2] [TYPE Function]
|
# region test_same_term_different_language_pair [C:2] [TYPE Function]
|
||||||
# @BRIEF Verify same term with different language pair is allowed.
|
# @BRIEF Verify same term with different language pair is allowed.
|
||||||
def test_same_term_different_language_pair(self, db_session: Session):
|
def test_same_term_different_language_pair(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Multi Lang", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Multi Lang")
|
||||||
entry1 = DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
entry1 = DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
||||||
entry2 = DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="de")
|
entry2 = DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="de")
|
||||||
assert entry1.id != entry2.id
|
assert entry1.id != entry2.id
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class TestFilterBasic:
|
|||||||
|
|
||||||
# region test_filter_for_batch_matches [C:2] [TYPE Function]
|
# region test_filter_for_batch_matches [C:2] [TYPE Function]
|
||||||
def test_filter_for_batch_matches(self, db_session: Session):
|
def test_filter_for_batch_matches(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test Dict", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test Dict")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "world", "mundo", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "world", "mundo", source_language="en", target_language="es")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "foo", "bar", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "foo", "bar", source_language="en", target_language="es")
|
||||||
@@ -76,7 +76,7 @@ class TestFilterBasic:
|
|||||||
|
|
||||||
# region test_filter_for_batch_case_insensitive [C:2] [TYPE Function]
|
# region test_filter_for_batch_case_insensitive [C:2] [TYPE Function]
|
||||||
def test_filter_for_batch_case_insensitive(self, db_session: Session):
|
def test_filter_for_batch_case_insensitive(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test Dict", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test Dict")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "Hello World", "Hola Mundo", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "Hello World", "Hola Mundo", source_language="en", target_language="es")
|
||||||
|
|
||||||
job = TranslationJob(name="Test Job", source_dialect="a", target_dialect="b", status="DRAFT")
|
job = TranslationJob(name="Test Job", source_dialect="a", target_dialect="b", status="DRAFT")
|
||||||
@@ -94,7 +94,7 @@ class TestFilterBasic:
|
|||||||
|
|
||||||
# region test_filter_for_batch_word_boundary [C:2] [TYPE Function]
|
# region test_filter_for_batch_word_boundary [C:2] [TYPE Function]
|
||||||
def test_filter_for_batch_word_boundary(self, db_session: Session):
|
def test_filter_for_batch_word_boundary(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test Dict", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test Dict")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "cat", "gato", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "cat", "gato", source_language="en", target_language="es")
|
||||||
|
|
||||||
job = TranslationJob(name="Test Job", source_dialect="a", target_dialect="b", status="DRAFT")
|
job = TranslationJob(name="Test Job", source_dialect="a", target_dialect="b", status="DRAFT")
|
||||||
@@ -117,8 +117,8 @@ class TestFilterPriority:
|
|||||||
|
|
||||||
# region test_filter_for_batch_multi_dictionary_priority [C:2] [TYPE Function]
|
# region test_filter_for_batch_multi_dictionary_priority [C:2] [TYPE Function]
|
||||||
def test_filter_for_batch_multi_dictionary_priority(self, db_session: Session):
|
def test_filter_for_batch_multi_dictionary_priority(self, db_session: Session):
|
||||||
d1 = DictionaryManager.create_dictionary(db_session, name="Priority1", source_dialect="a", target_dialect="b")
|
d1 = DictionaryManager.create_dictionary(db_session, name="Priority1")
|
||||||
d2 = DictionaryManager.create_dictionary(db_session, name="Priority2", source_dialect="a", target_dialect="b")
|
d2 = DictionaryManager.create_dictionary(db_session, name="Priority2")
|
||||||
DictionaryManager.add_entry(db_session, d1.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d1.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
DictionaryManager.add_entry(db_session, d2.id, "hello", "bonjour", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d2.id, "hello", "bonjour", source_language="en", target_language="es")
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ class TestFilterLanguagePair:
|
|||||||
|
|
||||||
# region test_filter_for_batch_with_language_pair [C:2] [TYPE Function]
|
# region test_filter_for_batch_with_language_pair [C:2] [TYPE Function]
|
||||||
def test_filter_for_batch_with_language_pair(self, db_session: Session):
|
def test_filter_for_batch_with_language_pair(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Lang Filter", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Lang Filter")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "world", "мир", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "world", "мир", source_language="en", target_language="ru")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="de")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="de")
|
||||||
@@ -169,7 +169,7 @@ class TestFilterLanguagePair:
|
|||||||
|
|
||||||
# region test_filter_for_batch_target_language_only [C:2] [TYPE Function]
|
# region test_filter_for_batch_target_language_only [C:2] [TYPE Function]
|
||||||
def test_filter_for_batch_target_language_only(self, db_session: Session):
|
def test_filter_for_batch_target_language_only(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Target Only", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Target Only")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="de")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hallo", source_language="en", target_language="de")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "bonjour", "hallo", source_language="fr", target_language="de")
|
DictionaryManager.add_entry(db_session, d.id, "bonjour", "hallo", source_language="fr", target_language="de")
|
||||||
@@ -196,7 +196,7 @@ class TestMigration:
|
|||||||
|
|
||||||
# region test_migrate_old_entries [C:2] [TYPE Function]
|
# region test_migrate_old_entries [C:2] [TYPE Function]
|
||||||
def test_migrate_old_entries(self, db_session: Session):
|
def test_migrate_old_entries(self, db_session: Session):
|
||||||
d = TerminologyDictionary(name="Old Dict", source_dialect="a", target_dialect="b")
|
d = TerminologyDictionary(name="Old Dict")
|
||||||
db_session.add(d)
|
db_session.add(d)
|
||||||
db_session.flush()
|
db_session.flush()
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class TestImportOverwrite:
|
|||||||
|
|
||||||
# region test_import_csv_overwrite [C:2] [TYPE Function]
|
# region test_import_csv_overwrite [C:2] [TYPE Function]
|
||||||
def test_import_csv_overwrite(self, db_session: Session):
|
def test_import_csv_overwrite(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
|
|
||||||
csv_content = "source_term,target_term,context_notes,source_language,target_language\nhello,HELLO,,en,es\nworld,mundo,,en,es"
|
csv_content = "source_term,target_term,context_notes,source_language,target_language\nhello,HELLO,,en,es\nworld,mundo,,en,es"
|
||||||
@@ -59,7 +59,7 @@ class TestImportKeepExisting:
|
|||||||
|
|
||||||
# region test_import_csv_keep_existing [C:2] [TYPE Function]
|
# region test_import_csv_keep_existing [C:2] [TYPE Function]
|
||||||
def test_import_csv_keep_existing(self, db_session: Session):
|
def test_import_csv_keep_existing(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
|
|
||||||
csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
|
csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
|
||||||
@@ -79,7 +79,7 @@ class TestImportCancel:
|
|||||||
|
|
||||||
# region test_import_csv_cancel_on_conflict [C:2] [TYPE Function]
|
# region test_import_csv_cancel_on_conflict [C:2] [TYPE Function]
|
||||||
def test_import_csv_cancel_on_conflict(self, db_session: Session):
|
def test_import_csv_cancel_on_conflict(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
|
|
||||||
csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
|
csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
|
||||||
@@ -97,7 +97,7 @@ class TestImportFormat:
|
|||||||
|
|
||||||
# region test_import_tsv [C:2] [TYPE Function]
|
# region test_import_tsv [C:2] [TYPE Function]
|
||||||
def test_import_tsv(self, db_session: Session):
|
def test_import_tsv(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
tsv_content = "source_term\ttarget_term\tsource_language\ttarget_language\nhello\thola\ten\tes\nworld\tmundo\ten\tes"
|
tsv_content = "source_term\ttarget_term\tsource_language\ttarget_language\nhello\thola\ten\tes\nworld\tmundo\ten\tes"
|
||||||
result = DictionaryManager.import_entries(db_session, d.id, tsv_content, delimiter="\t", on_conflict="overwrite")
|
result = DictionaryManager.import_entries(db_session, d.id, tsv_content, delimiter="\t", on_conflict="overwrite")
|
||||||
assert result["created"] == 2
|
assert result["created"] == 2
|
||||||
@@ -106,14 +106,14 @@ class TestImportFormat:
|
|||||||
|
|
||||||
# region test_import_invalid_format [C:2] [TYPE Function]
|
# region test_import_invalid_format [C:2] [TYPE Function]
|
||||||
def test_import_invalid_format(self, db_session: Session):
|
def test_import_invalid_format(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
with pytest.raises(ValueError, match="source_term"):
|
with pytest.raises(ValueError, match="source_term"):
|
||||||
DictionaryManager.import_entries(db_session, d.id, "name,value\nhello,hola", delimiter=",", on_conflict="overwrite")
|
DictionaryManager.import_entries(db_session, d.id, "name,value\nhello,hola", delimiter=",", on_conflict="overwrite")
|
||||||
# endregion test_import_invalid_format
|
# endregion test_import_invalid_format
|
||||||
|
|
||||||
# region test_import_empty_rows [C:2] [TYPE Function]
|
# region test_import_empty_rows [C:2] [TYPE Function]
|
||||||
def test_import_empty_rows(self, db_session: Session):
|
def test_import_empty_rows(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
csv_content = "source_term,target_term\nhello,hola\n,world\nfoo,"
|
csv_content = "source_term,target_term\nhello,hola\n,world\nfoo,"
|
||||||
result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite")
|
result = DictionaryManager.import_entries(db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite")
|
||||||
assert result["created"] == 1
|
assert result["created"] == 1
|
||||||
@@ -122,7 +122,7 @@ class TestImportFormat:
|
|||||||
|
|
||||||
# region test_import_preview [C:2] [TYPE Function]
|
# region test_import_preview [C:2] [TYPE Function]
|
||||||
def test_import_preview(self, db_session: Session):
|
def test_import_preview(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "hola", source_language="en", target_language="es")
|
||||||
|
|
||||||
csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
|
csv_content = "source_term,target_term,source_language,target_language\nhello,HELLO,en,es\nworld,mundo,en,es"
|
||||||
@@ -142,7 +142,7 @@ class TestExportEntries:
|
|||||||
|
|
||||||
# region test_export_entries [C:2] [TYPE Function]
|
# region test_export_entries [C:2] [TYPE Function]
|
||||||
def test_export_entries(self, db_session: Session):
|
def test_export_entries(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Export Test", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Export Test")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "hello", "привет", source_language="en", target_language="ru")
|
||||||
DictionaryManager.add_entry(db_session, d.id, "world", "мир", source_language="en", target_language="ru")
|
DictionaryManager.add_entry(db_session, d.id, "world", "мир", source_language="en", target_language="ru")
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ class TestExportEntries:
|
|||||||
|
|
||||||
# region test_import_with_default_language [C:2] [TYPE Function]
|
# region test_import_with_default_language [C:2] [TYPE Function]
|
||||||
def test_import_with_default_language(self, db_session: Session):
|
def test_import_with_default_language(self, db_session: Session):
|
||||||
d = DictionaryManager.create_dictionary(db_session, name="Default Lang Import", source_dialect="a", target_dialect="b")
|
d = DictionaryManager.create_dictionary(db_session, name="Default Lang Import")
|
||||||
csv_content = "source_term,target_term\nhello,привет\nworld,мир"
|
csv_content = "source_term,target_term\nhello,привет\nworld,мир"
|
||||||
result = DictionaryManager.import_entries(
|
result = DictionaryManager.import_entries(
|
||||||
db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite",
|
db_session, d.id, csv_content, delimiter=",", on_conflict="overwrite",
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ class DictionaryCorrectionService:
|
|||||||
effective_context_source = "manual"
|
effective_context_source = "manual"
|
||||||
|
|
||||||
normalized = _normalize_term(source_term)
|
normalized = _normalize_term(source_term)
|
||||||
entry_src_lang = dictionary.source_dialect or "und"
|
entry_src_lang = "und"
|
||||||
entry_tgt_lang = dictionary.target_dialect or "und"
|
entry_tgt_lang = "und"
|
||||||
|
|
||||||
existing = (
|
existing = (
|
||||||
db.query(DictionaryEntry)
|
db.query(DictionaryEntry)
|
||||||
@@ -139,8 +139,8 @@ class DictionaryCorrectionService:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
normalized = _normalize_term(source_term)
|
normalized = _normalize_term(source_term)
|
||||||
bulk_src_lang = dictionary.source_dialect or "und"
|
bulk_src_lang = "und"
|
||||||
bulk_tgt_lang = dictionary.target_dialect or "und"
|
bulk_tgt_lang = "und"
|
||||||
|
|
||||||
existing = (
|
existing = (
|
||||||
db.query(DictionaryEntry)
|
db.query(DictionaryEntry)
|
||||||
|
|||||||
@@ -24,15 +24,13 @@ class DictionaryCRUD:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def create_dictionary(
|
def create_dictionary(
|
||||||
db: Session, name: str,
|
db: Session, name: str,
|
||||||
source_dialect: str = "", target_dialect: str = "",
|
|
||||||
created_by: str | None = None, description: str | None = None,
|
created_by: str | None = None, description: str | None = None,
|
||||||
is_active: bool = True,
|
is_active: bool = True,
|
||||||
) -> TerminologyDictionary:
|
) -> TerminologyDictionary:
|
||||||
with belief_scope("DictionaryCRUD.create_dictionary"):
|
with belief_scope("DictionaryCRUD.create_dictionary"):
|
||||||
logger.reason("Creating dictionary", {"name": name, "source": source_dialect, "target": target_dialect})
|
logger.reason("Creating dictionary", {"name": name})
|
||||||
dictionary = TerminologyDictionary(
|
dictionary = TerminologyDictionary(
|
||||||
name=name, description=description,
|
name=name, description=description,
|
||||||
source_dialect=source_dialect or "", target_dialect=target_dialect or "",
|
|
||||||
is_active=is_active, created_by=created_by,
|
is_active=is_active, created_by=created_by,
|
||||||
)
|
)
|
||||||
db.add(dictionary)
|
db.add(dictionary)
|
||||||
@@ -47,8 +45,7 @@ class DictionaryCRUD:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def update_dictionary(
|
def update_dictionary(
|
||||||
db: Session, dict_id: str, name: str | None = None,
|
db: Session, dict_id: str, name: str | None = None,
|
||||||
description: str | None = None, source_dialect: str | None = None,
|
description: str | None = None, is_active: bool | None = None,
|
||||||
target_dialect: str | None = None, is_active: bool | None = None,
|
|
||||||
) -> TerminologyDictionary:
|
) -> TerminologyDictionary:
|
||||||
with belief_scope("DictionaryCRUD.update_dictionary"):
|
with belief_scope("DictionaryCRUD.update_dictionary"):
|
||||||
dictionary = db.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first()
|
dictionary = db.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first()
|
||||||
@@ -59,10 +56,6 @@ class DictionaryCRUD:
|
|||||||
dictionary.name = name
|
dictionary.name = name
|
||||||
if description is not None:
|
if description is not None:
|
||||||
dictionary.description = description
|
dictionary.description = description
|
||||||
if source_dialect is not None:
|
|
||||||
dictionary.source_dialect = source_dialect
|
|
||||||
if target_dialect is not None:
|
|
||||||
dictionary.target_dialect = target_dialect
|
|
||||||
if is_active is not None:
|
if is_active is not None:
|
||||||
dictionary.is_active = is_active
|
dictionary.is_active = is_active
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|||||||
@@ -173,8 +173,6 @@ class DuplicateJobResponse(BaseModel):
|
|||||||
class DictionaryCreate(BaseModel):
|
class DictionaryCreate(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
description: str | None = None
|
description: str | None = None
|
||||||
source_dialect: str
|
|
||||||
target_dialect: str
|
|
||||||
is_active: bool = True
|
is_active: bool = True
|
||||||
# #endregion DictionaryCreate
|
# #endregion DictionaryCreate
|
||||||
|
|
||||||
@@ -197,8 +195,6 @@ class DictionaryResponse(BaseModel):
|
|||||||
id: str
|
id: str
|
||||||
name: str
|
name: str
|
||||||
description: str | None = None
|
description: str | None = None
|
||||||
source_dialect: str
|
|
||||||
target_dialect: str
|
|
||||||
is_active: bool
|
is_active: bool
|
||||||
created_by: str | None = None
|
created_by: str | None = None
|
||||||
created_at: datetime
|
created_at: datetime
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ def client(mock_api_deps):
|
|||||||
def test_submit_correction_creates_entry(db_session):
|
def test_submit_correction_creates_entry(db_session):
|
||||||
"""Test that submitting a correction creates a new entry."""
|
"""Test that submitting a correction creates a new entry."""
|
||||||
dict_obj = DictionaryManager.create_dictionary(
|
dict_obj = DictionaryManager.create_dictionary(
|
||||||
db_session, name="Test Dict", source_dialect="en", target_dialect="ru",
|
db_session, name="Test Dict",
|
||||||
created_by="testuser",
|
created_by="testuser",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ def test_submit_correction_creates_entry(db_session):
|
|||||||
def test_submit_correction_conflict_detected(db_session):
|
def test_submit_correction_conflict_detected(db_session):
|
||||||
"""Test that conflict is detected when entry already exists."""
|
"""Test that conflict is detected when entry already exists."""
|
||||||
dict_obj = DictionaryManager.create_dictionary(
|
dict_obj = DictionaryManager.create_dictionary(
|
||||||
db_session, name="Dict", source_dialect="en", target_dialect="ru",
|
db_session, name="Dict",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create initial entry
|
# Create initial entry
|
||||||
@@ -165,7 +165,7 @@ def test_submit_correction_conflict_detected(db_session):
|
|||||||
def test_submit_correction_overwrite(db_session):
|
def test_submit_correction_overwrite(db_session):
|
||||||
"""Test that correction overwrites existing entry."""
|
"""Test that correction overwrites existing entry."""
|
||||||
dict_obj = DictionaryManager.create_dictionary(
|
dict_obj = DictionaryManager.create_dictionary(
|
||||||
db_session, name="Dict", source_dialect="en", target_dialect="ru",
|
db_session, name="Dict",
|
||||||
)
|
)
|
||||||
|
|
||||||
DictionaryManager.add_entry(db_session, dict_obj.id, "hello", "privet")
|
DictionaryManager.add_entry(db_session, dict_obj.id, "hello", "privet")
|
||||||
@@ -190,7 +190,7 @@ def test_submit_correction_overwrite(db_session):
|
|||||||
def test_bulk_corrections_atomic(db_session):
|
def test_bulk_corrections_atomic(db_session):
|
||||||
"""Test that bulk corrections are applied atomically."""
|
"""Test that bulk corrections are applied atomically."""
|
||||||
dict_obj = DictionaryManager.create_dictionary(
|
dict_obj = DictionaryManager.create_dictionary(
|
||||||
db_session, name="Bulk Dict", source_dialect="en", target_dialect="ru",
|
db_session, name="Bulk Dict",
|
||||||
)
|
)
|
||||||
|
|
||||||
corrections = [
|
corrections = [
|
||||||
@@ -233,7 +233,7 @@ def test_api_bulk_corrections(client, mock_api_deps):
|
|||||||
"""Test bulk corrections endpoint."""
|
"""Test bulk corrections endpoint."""
|
||||||
session = mock_api_deps["session"]
|
session = mock_api_deps["session"]
|
||||||
dict_obj = DictionaryManager.create_dictionary(
|
dict_obj = DictionaryManager.create_dictionary(
|
||||||
session, name="API Dict", source_dialect="en", target_dialect="ru",
|
session, name="API Dict",
|
||||||
)
|
)
|
||||||
|
|
||||||
response = client.post("/api/translate/corrections/bulk", json={
|
response = client.post("/api/translate/corrections/bulk", json={
|
||||||
|
|||||||
Reference in New Issue
Block a user