Source code for flexicon.code.TextsWords.WfiGlossOperations

#
#   WfiGlossOperations.py
#
#   Class: WfiGlossOperations
#          Wordform gloss operations for FieldWorks Language Explorer projects
#          via SIL Language and Culture Model (LCM) API.
#
#   Platform: Python.NET
#             FieldWorks Version 9+
#
#   Copyright 2025
#

import clr

clr.AddReference("System")

from SIL.LCModel import (
    IWfiGloss,
    IWfiGlossFactory,
    IWfiAnalysis,
)

from SIL.LCModel.Core.KernelInterfaces import ITsString
from SIL.LCModel.Core.Text import TsStringUtils

from ..FLExProject import (
    FP_ParameterError,
)
from ..BaseOperations import BaseOperations, OperationsMethod, wrap_enumerable
from ..Shared.string_utils import normalize_match_key

# --- WfiGlossOperations Class ---


[docs] class WfiGlossOperations(BaseOperations): """ Provides operations for managing wordform glosses (WfiGloss) in a FLEx project. WfiGloss objects represent glosses (meanings/translations) for wordform analyses. Each WfiAnalysis can have multiple glosses in different writing systems. Glosses provide the semantic interpretation of an analyzed wordform. This class should be accessed via FLExProject.WfiGlosses property. Example: >>> project = FLExProject() >>> project.OpenProject("MyProject", writeEnabled=True) >>> # Get a wordform and its first analysis >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... analysis = analyses[0] ... # Get all glosses for the analysis ... for gloss in project.WfiGlosses.GetAll(analysis): ... form = project.WfiGlosses.GetForm(gloss) ... print(f"Gloss: {form}") ... # Create a new gloss ... new_gloss = project.WfiGlosses.Create(analysis, "running", "en") ... # Update gloss form ... project.WfiGlosses.SetForm(new_gloss, "to run", "en") >>> project.CloseProject() """ def __init__(self, project): """ Initialize WfiGlossOperations. Args: project: FLExProject instance """ super().__init__(project) def __WSHandle(self, wsHandle): """ Internal helper to resolve writing system handle. Args: wsHandle: Writing system handle (language tag or ID), or None for default Returns: int: Resolved writing system handle """ if wsHandle is None: return self.project.project.DefaultAnalWs return self.project._FLExProject__WSHandle(wsHandle, self.project.project.DefaultAnalWs) # --- Core CRUD Operations --- @wrap_enumerable @OperationsMethod def GetAll(self, analysis_or_hvo): """ Retrieve all glosses for a wordform analysis. This method returns an iterator over all IWfiGloss objects associated with the specified analysis, allowing iteration over all meaning glosses. Args: analysis_or_hvo: Either an IWfiAnalysis object or its HVO Yields: IWfiGloss: Each gloss object for the analysis Raises: FP_NullParameterError: If analysis_or_hvo is None FP_ParameterError: If analysis doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... for gloss in project.WfiGlosses.GetAll(analyses[0]): ... form = project.WfiGlosses.GetForm(gloss) ... print(form) Notes: - Returns an iterator for memory efficiency - Glosses are returned in the order they were added - Returns empty iterator if analysis has no glosses - Each gloss can have forms in multiple writing systems See Also: Create, Find, GetForm """ self._ValidateParam(analysis_or_hvo, "analysis_or_hvo") # Resolve to analysis object if isinstance(analysis_or_hvo, int): analysis = self.project.Object(analysis_or_hvo) if not isinstance(analysis, IWfiAnalysis): raise FP_ParameterError("HVO does not refer to a wordform analysis") else: analysis = analysis_or_hvo # Yield all glosses from the Meanings collection for gloss in analysis.MeaningsOC: yield gloss @OperationsMethod def Create(self, analysis_or_hvo, form, wsHandle=None): """ Create a new gloss for a wordform analysis. Args: analysis_or_hvo: Either an IWfiAnalysis object or its HVO form: The gloss text (meaning/translation) wsHandle: Optional writing system handle. Defaults to analysis WS. Returns: IWfiGloss: The newly created gloss object Raises: FP_ReadOnlyError: If project is not opened with write enabled FP_NullParameterError: If analysis_or_hvo or form is None FP_ParameterError: If form is empty or analysis doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... gloss = project.WfiGlosses.Create(analyses[0], "to run") ... print(project.WfiGlosses.GetForm(gloss)) to run >>> # Create with specific writing system >>> gloss_fr = project.WfiGlosses.Create(analyses[0], "courir", "fr") Notes: - New gloss is added to the analysis's Meanings collection - The form is stored in the specified writing system - Duplicate glosses are allowed (no uniqueness check) - Gloss is added at the end of the collection See Also: Delete, SetForm, GetAll """ self._EnsureWriteEnabled() self._ValidateParam(analysis_or_hvo, "analysis_or_hvo") self._ValidateParam(form, "form") if not form or not form.strip(): raise FP_ParameterError("Gloss form cannot be empty") # Resolve to analysis object if isinstance(analysis_or_hvo, int): analysis = self.project.Object(analysis_or_hvo) if not isinstance(analysis, IWfiAnalysis): raise FP_ParameterError("HVO does not refer to a wordform analysis") else: analysis = analysis_or_hvo wsHandle = self.__WSHandle(wsHandle) with self._TransactionCM("Create gloss"): # Get the factory and create the gloss factory = self.project.project.ServiceLocator.GetService(IWfiGlossFactory) new_gloss = factory.Create() # Add to analysis's Meanings collection (must be done before setting properties) analysis.MeaningsOC.Add(new_gloss) # Set the form mkstr = TsStringUtils.MakeString(form, wsHandle) new_gloss.Form.set_String(wsHandle, mkstr) return new_gloss # ========== SYNC INTEGRATION METHODS ========== @OperationsMethod def GetSyncableProperties(self, item): """ Get all syncable properties of a wordform gloss. Args: item: The IWfiGloss object. Returns: dict: Dictionary of syncable properties with their values. Example: >>> props = project.WfiGlosses.GetSyncableProperties(gloss) >>> print(props['Form']) {'en': 'running', 'es': 'corriendo'} Notes: - MultiString property: Form - Form contains gloss text in multiple writing systems """ props = {} # MultiString property - Form if hasattr(item, "Form") and item.Form: props["Form"] = self.project.GetMultiStringDict(item.Form) return props @OperationsMethod def CompareTo(self, item1, item2, ops1=None, ops2=None): """ Compare two wordform glosses for differences. Args: item1: First gloss object (from project 1) item2: Second gloss object (from project 2) ops1: Optional WfiGlossOperations instance for project 1 (defaults to self) ops2: Optional WfiGlossOperations instance for project 2 (defaults to self) Returns: tuple: (is_different, differences_dict) - is_different (bool): True if glosses differ, False if identical - differences_dict (dict): Maps property names to (value1, value2) tuples Example: >>> is_diff, diffs = ops1.CompareTo(gloss1, gloss2, ops1, ops2) >>> if is_diff: ... for prop, (val1, val2) in diffs.items(): ... print(f"{prop}: {val1} != {val2}") Notes: - Compares Form MultiString across all writing systems - Empty/null values are treated as equivalent """ if ops1 is None: ops1 = self if ops2 is None: ops2 = self props1 = ops1.GetSyncableProperties(item1) props2 = ops2.GetSyncableProperties(item2) differences = {} # Get all property keys from both items all_keys = set(props1.keys()) | set(props2.keys()) for key in all_keys: val1 = props1.get(key) val2 = props2.get(key) # Compare values if self.project._CompareValues(val1, val2): # Values are different differences[key] = (val1, val2) is_different = len(differences) > 0 return (is_different, differences) @OperationsMethod def Delete(self, gloss_or_hvo): """ Delete a gloss from its owning analysis. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO Raises: FP_ReadOnlyError: If project is not opened with write enabled FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if len(glosses) > 1: ... # Delete the last gloss ... project.WfiGlosses.Delete(glosses[-1]) Warning: - This is a destructive operation - Deletion is permanent and cannot be undone - Consider backing up data before deletion - Text segments that reference this gloss may be affected See Also: Create, GetAll """ self._EnsureWriteEnabled() self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo # Get the owning analysis; MeaningsOC is declared on IWfiAnalysis so # cast unconditionally to surface the typed collection accessor. analysis = IWfiAnalysis(gloss.Owner) # Remove from analysis's Meanings collection analysis.MeaningsOC.Remove(gloss) @OperationsMethod def Duplicate(self, item_or_hvo, insert_after=False): """ Duplicate a wordform gloss, creating a new copy with a new GUID. Args: item_or_hvo: The IWfiGloss object or HVO to duplicate. insert_after (bool): Ignored. MeaningsOC is an unordered ILcmOwningCollection with no Insert() method and no concept of positional ordering. The duplicate is always appended via Add(). Returns: IWfiGloss: The newly created duplicate gloss with a new GUID. Raises: FP_ReadOnlyError: If the project is not opened with write enabled. FP_NullParameterError: If item_or_hvo is None. Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... # Duplicate gloss ... dup = project.WfiGlosses.Duplicate(glosses[0]) ... print(f"Original: {project.WfiGlosses.GetGuid(glosses[0])}") ... print(f"Duplicate: {project.WfiGlosses.GetGuid(dup)}") Original: 12345678-1234-1234-1234-123456789abc Duplicate: 87654321-4321-4321-4321-cba987654321 ... ... # Verify content was copied ... print(f"Form: {project.WfiGlosses.GetForm(dup)}") Notes: - Factory.Create() automatically generates a new GUID - MeaningsOC is unordered; the duplicate is appended via Add() - Simple properties copied: Form (MultiString in all writing systems) - Reference properties: None (WfiGloss has no reference properties) - WfiGloss has no owned objects, so deep parameter has no effect See Also: Create, Delete, GetGuid """ self._EnsureWriteEnabled() self._ValidateParam(item_or_hvo, "item_or_hvo") # Resolve to gloss object if isinstance(item_or_hvo, int): source = self.project.Object(item_or_hvo) if not isinstance(source, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: source = item_or_hvo parent = self._GetObject(source.Owner.Hvo) with self._TransactionCM("Duplicate gloss"): # Create new gloss using factory (auto-generates new GUID) factory = self.project.project.ServiceLocator.GetService(IWfiGlossFactory) duplicate = factory.Create() # MeaningsOC is unordered; always append via Add(). parent.MeaningsOC.Add(duplicate) # Copy simple MultiString properties duplicate.Form.CopyAlternatives(source.Form) # Note: WfiGloss has no owned objects (OS collections), so deep has no effect return duplicate # --- Form Management Operations --- @OperationsMethod def GetForm(self, gloss_or_hvo, wsHandle=None): """ Get the gloss text form. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO wsHandle: Optional writing system handle. Defaults to analysis WS. Returns: str: The gloss text (empty string if not set) Raises: FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... for gloss in project.WfiGlosses.GetAll(analyses[0]): ... form = project.WfiGlosses.GetForm(gloss) ... print(form) Notes: - Returns empty string if form not set in specified writing system - Default writing system is the default analysis WS - Gloss can have different forms in multiple writing systems See Also: SetForm, GetAllForms """ self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo wsHandle = self.__WSHandle(wsHandle) # Get the form string form = ITsString(gloss.Form.get_String(wsHandle)).Text return form or "" @OperationsMethod def SetForm(self, gloss_or_hvo, text, wsHandle=None): """ Set the gloss text form. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO text: The new gloss text wsHandle: Optional writing system handle. Defaults to analysis WS. Raises: FP_ReadOnlyError: If project is not opened with write enabled FP_NullParameterError: If gloss_or_hvo or text is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... project.WfiGlosses.SetForm(glosses[0], "to run quickly") ... print(project.WfiGlosses.GetForm(glosses[0])) to run quickly >>> # Set form in multiple writing systems >>> project.WfiGlosses.SetForm(glosses[0], "courir", "fr") >>> project.WfiGlosses.SetForm(glosses[0], "correr", "es") Notes: - Empty string is allowed (clears the gloss in that writing system) - Gloss can be set independently in multiple writing systems - Use this to provide translations in different languages See Also: GetForm, Create """ self._EnsureWriteEnabled() self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") self._ValidateParam(text, "text") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo wsHandle = self.__WSHandle(wsHandle) # Set the form string mkstr = TsStringUtils.MakeString(text, wsHandle) gloss.Form.set_String(wsHandle, mkstr) @OperationsMethod def GetAllForms(self, gloss_or_hvo): """ Get all available forms for a gloss across all writing systems. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO Returns: dict: Dictionary mapping writing system handles to form text Raises: FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... forms = project.WfiGlosses.GetAllForms(glosses[0]) ... for ws_handle, form in forms.items(): ... print(f"WS {ws_handle}: {form}") Notes: - Returns only writing systems where form is set - Dictionary keys are writing system handles (integers) - Use project.GetWritingSystemName(ws) to get WS names - Empty forms are excluded from results See Also: GetForm, SetForm """ self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo forms = {} # Iterate through available writing systems for ws in gloss.Form.AvailableWritingSystemIds: form_text = ITsString(gloss.Form.get_String(ws)).Text if form_text: forms[ws] = form_text return forms # --- Utility Operations --- @OperationsMethod def GetOwningAnalysis(self, gloss_or_hvo): """ Get the wordform analysis that owns this gloss. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO Returns: IWfiAnalysis: The owning analysis object Raises: FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> # Find a gloss and get its owning analysis >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... analysis = project.WfiGlosses.GetOwningAnalysis(glosses[0]) ... print(f"Analysis HVO: {analysis.Hvo}") Notes: - Gloss is owned by exactly one analysis - Use this to navigate from gloss back to analysis - Useful for accessing other analysis properties See Also: GetAll, GetGuid """ self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo # Cast to declared return type IWfiAnalysis. Raw gloss.Owner is typed # as ICmObject in LCM; pythonnet only surfaces IWfiAnalysis properties # (e.g. MorphBundlesOS) after the explicit interface cast. return IWfiAnalysis(gloss.Owner) @OperationsMethod def GetGuid(self, gloss_or_hvo): """ Get the GUID (Global Unique Identifier) for a gloss. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO Returns: System.Guid: The GUID of the gloss Raises: FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... guid = project.WfiGlosses.GetGuid(glosses[0]) ... print(f"Gloss GUID: {guid}") Notes: - GUID is unique across all projects - GUID remains constant even if object moves - Useful for cross-referencing between projects - HVO is project-specific, GUID is universal See Also: GetOwningAnalysis, Find """ self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo return gloss.Guid @OperationsMethod def Find(self, analysis_or_hvo, form, wsHandle=None): """ Find and return a gloss by its form text. Args: analysis_or_hvo: Either an IWfiAnalysis object or its HVO form: The gloss text to find wsHandle: Optional writing system handle. Defaults to analysis WS. Returns: IWfiGloss or None: The gloss object if found, None otherwise Raises: FP_NullParameterError: If analysis_or_hvo or form is None FP_ParameterError: If analysis doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... gloss = project.WfiGlosses.Find(analyses[0], "to run") ... if gloss: ... print(f"Found gloss: {gloss.Hvo}") ... else: ... print("Gloss not found") Notes: - Search is case-sensitive - Search is writing-system specific - Returns None if gloss doesn't exist - Returns first match if multiple glosses have same form - Use Exists() for simple existence check See Also: Exists, GetAll, Create """ self._ValidateParam(analysis_or_hvo, "analysis_or_hvo") self._ValidateParam(form, "form") if not form or not form.strip(): return None # Resolve to analysis object if isinstance(analysis_or_hvo, int): analysis = self.project.Object(analysis_or_hvo) if not isinstance(analysis, IWfiAnalysis): raise FP_ParameterError("HVO does not refer to a wordform analysis") else: analysis = analysis_or_hvo wsHandle = self.__WSHandle(wsHandle) # Search through all glosses target = normalize_match_key(form, casefold=False) for gloss in self.GetAll(analysis): gloss_form = ITsString(gloss.Form.get_String(wsHandle)).Text if normalize_match_key(gloss_form, casefold=False) == target: return gloss return None @OperationsMethod def Exists(self, analysis_or_hvo, form, wsHandle=None): """ Check if a gloss with the specified form exists for an analysis. Args: analysis_or_hvo: Either an IWfiAnalysis object or its HVO form: The gloss text to check wsHandle: Optional writing system handle. Defaults to analysis WS. Returns: bool: True if the gloss exists, False otherwise Raises: FP_NullParameterError: If analysis_or_hvo or form is None FP_ParameterError: If analysis doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... if project.WfiGlosses.Exists(analyses[0], "to run"): ... gloss = project.WfiGlosses.Find(analyses[0], "to run") ... else: ... gloss = project.WfiGlosses.Create(analyses[0], "to run") Notes: - Search is case-sensitive - Search is writing-system specific - Returns False for empty or whitespace-only forms - More efficient than Find() when you only need existence check See Also: Find, Create """ self._ValidateParam(analysis_or_hvo, "analysis_or_hvo") self._ValidateParam(form, "form") if not form or not form.strip(): return False return self.Find(analysis_or_hvo, form, wsHandle) is not None @OperationsMethod def GetCount(self, analysis_or_hvo): """ Get the count of glosses for a wordform analysis. Args: analysis_or_hvo: Either an IWfiAnalysis object or its HVO Returns: int: Number of glosses Raises: FP_NullParameterError: If analysis_or_hvo is None FP_ParameterError: If analysis doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... count = project.WfiGlosses.GetCount(analyses[0]) ... print(f"This analysis has {count} glosses") Notes: - More efficient than len(list(GetAll())) for counting - Returns 0 if analysis has no glosses - Each gloss may have forms in multiple writing systems See Also: GetAll, Create """ self._ValidateParam(analysis_or_hvo, "analysis_or_hvo") # Resolve to analysis object if isinstance(analysis_or_hvo, int): analysis = self.project.Object(analysis_or_hvo) if not isinstance(analysis, IWfiAnalysis): raise FP_ParameterError("HVO does not refer to a wordform analysis") else: analysis = analysis_or_hvo return analysis.MeaningsOC.Count @OperationsMethod def GetBestForm(self, gloss_or_hvo): """ Get the best available form for a gloss. This method attempts to find a suitable gloss form by checking writing systems in order of preference: default analysis WS, then any available WS. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO Returns: str: The best available gloss form (empty string if none found) Raises: FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... for gloss in project.WfiGlosses.GetAll(analyses[0]): ... best = project.WfiGlosses.GetBestForm(gloss) ... print(f"Best form: {best}") Notes: - Tries default analysis WS first - Falls back to first available WS if default not set - Returns empty string if no forms are set - Useful when you need any available form See Also: GetForm, GetAllForms """ self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): gloss = self.project.Object(gloss_or_hvo) if not isinstance(gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: gloss = gloss_or_hvo # Try default analysis WS first default_ws = self.project.project.DefaultAnalWs best_form = ITsString(gloss.Form.get_String(default_ws)).Text if best_form: return best_form # Try any available writing system for ws in gloss.Form.AvailableWritingSystemIds: form_text = ITsString(gloss.Form.get_String(ws)).Text if form_text: return form_text return "" @OperationsMethod def CopyGloss(self, gloss_or_hvo, target_analysis_or_hvo): """ Copy a gloss to another analysis. Creates a new gloss in the target analysis with all forms from the source gloss. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO (source) target_analysis_or_hvo: Either an IWfiAnalysis object or its HVO (target) Returns: IWfiGloss: The newly created gloss in the target analysis Raises: FP_ReadOnlyError: If project is not opened with write enabled FP_NullParameterError: If gloss_or_hvo or target_analysis_or_hvo is None FP_ParameterError: If gloss or analysis doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if len(analyses) > 1: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... # Copy first gloss from first analysis to second ... new_gloss = project.WfiGlosses.CopyGloss(glosses[0], analyses[1]) ... print(f"Copied gloss: {project.WfiGlosses.GetForm(new_gloss)}") Notes: - Copies all writing system forms from source to target - Creates a new gloss object (not a reference) - Useful for sharing glosses between analyses See Also: Create, GetAllForms """ self._EnsureWriteEnabled() self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") self._ValidateParam(target_analysis_or_hvo, "target_analysis_or_hvo") # Resolve to gloss object if isinstance(gloss_or_hvo, int): source_gloss = self.project.Object(gloss_or_hvo) if not isinstance(source_gloss, IWfiGloss): raise FP_ParameterError("HVO does not refer to a wordform gloss") else: source_gloss = gloss_or_hvo # Resolve to target analysis object if isinstance(target_analysis_or_hvo, int): target_analysis = self.project.Object(target_analysis_or_hvo) if not isinstance(target_analysis, IWfiAnalysis): raise FP_ParameterError("HVO does not refer to a wordform analysis") else: target_analysis = target_analysis_or_hvo with self._TransactionCM("Copy gloss"): # Create new gloss factory = self.project.project.ServiceLocator.GetService(IWfiGlossFactory) new_gloss = factory.Create() # Add to target analysis (must be done before setting properties) target_analysis.MeaningsOC.Add(new_gloss) # Copy all forms for ws in source_gloss.Form.AvailableWritingSystemIds: form_text = ITsString(source_gloss.Form.get_String(ws)).Text if form_text: mkstr = TsStringUtils.MakeString(form_text, ws) new_gloss.Form.set_String(ws, mkstr) return new_gloss @OperationsMethod def ClearForm(self, gloss_or_hvo, wsHandle=None): """ Clear the form for a gloss in a specific writing system. Args: gloss_or_hvo: Either an IWfiGloss object or its HVO wsHandle: Optional writing system handle. Defaults to analysis WS. Raises: FP_ReadOnlyError: If project is not opened with write enabled FP_NullParameterError: If gloss_or_hvo is None FP_ParameterError: If gloss doesn't exist Example: >>> wf = project.Wordforms.Find("running") >>> analyses = project.Wordforms.GetAnalyses(wf) >>> if analyses: ... glosses = list(project.WfiGlosses.GetAll(analyses[0])) ... if glosses: ... # Clear the English form ... project.WfiGlosses.ClearForm(glosses[0], "en") Notes: - Only clears the form in the specified writing system - Forms in other writing systems are not affected - Equivalent to SetForm(gloss, "", ws) - Gloss object itself is not deleted See Also: SetForm, Delete """ self._EnsureWriteEnabled() self._ValidateParam(gloss_or_hvo, "gloss_or_hvo") self.SetForm(gloss_or_hvo, "", wsHandle)