Skip to content

glazing.search

Unified search interface for all linguistic datasets.

search

Unified search interface for all linguistic datasets.

This module provides a unified interface for searching across FrameNet, VerbNet, WordNet, and PropBank data simultaneously. All datasets are loaded automatically when UnifiedSearch is initialized.

CLASS DESCRIPTION
SearchResult

Individual search result.

UnifiedSearch

Unified search interface across all linguistic datasets.

UnifiedSearchResult

Container for search results across all datasets.

Classes

SearchResult(dataset: str, id: str, type: str, name: str, description: str, score: float) dataclass

Individual search result.

PARAMETER DESCRIPTION
dataset

Source dataset name.

TYPE: str

id

Entity identifier.

TYPE: str

type

Entity type.

TYPE: str

name

Entity name.

TYPE: str

description

Entity description.

TYPE: str

score

Relevance score.

TYPE: float

UnifiedSearch(data_dir: Path | str | None = None, framenet: FrameNetSearch | None = None, verbnet: VerbNetSearch | None = None, wordnet: WordNetSearch | None = None, propbank: PropBankSearch | None = None, auto_load: bool = True)

Unified search interface across all linguistic datasets.

Provides methods for searching FrameNet, VerbNet, WordNet, and PropBank simultaneously or individually.

PARAMETER DESCRIPTION
framenet

FrameNet search index.

TYPE: FrameNetSearch | None DEFAULT: None

verbnet

VerbNet search index.

TYPE: VerbNetSearch | None DEFAULT: None

wordnet

WordNet search index.

TYPE: WordNetSearch | None DEFAULT: None

propbank

PropBank search index.

TYPE: PropBankSearch | None DEFAULT: None

ATTRIBUTE DESCRIPTION
framenet

FrameNet search interface.

TYPE: FrameNetSearch | None

verbnet

VerbNet search interface.

TYPE: VerbNetSearch | None

wordnet

WordNet search interface.

TYPE: WordNetSearch | None

propbank

PropBank search interface.

TYPE: PropBankSearch | None

METHOD DESCRIPTION
by_lemma

Search all datasets by lemma.

by_semantic_role

Search for frames/classes with a semantic role.

by_semantic_predicate

Search for verb classes with a semantic predicate.

by_domain

Search within a specific domain.

get_statistics

Get statistics across all datasets.

Examples:

>>> search = UnifiedSearch(
...     framenet=FrameNetSearch(frames),
...     verbnet=VerbNetSearch(classes),
...     wordnet=WordNetSearch(synsets),
...     propbank=PropBankSearch(framesets)
... )
>>> results = search.by_lemma("give")

Initialize unified search.

PARAMETER DESCRIPTION
data_dir

Directory containing converted data files. If None, uses default path from environment.

TYPE: Path | str | None DEFAULT: None

framenet

Pre-initialized FrameNet search object.

TYPE: FrameNetSearch | None DEFAULT: None

verbnet

Pre-initialized VerbNet search object.

TYPE: VerbNetSearch | None DEFAULT: None

wordnet

Pre-initialized WordNet search object.

TYPE: WordNetSearch | None DEFAULT: None

propbank

Pre-initialized PropBank search object.

TYPE: PropBankSearch | None DEFAULT: None

auto_load

If True and no search objects provided, automatically loads from data_dir.

TYPE: bool DEFAULT: True

Source code in src/glazing/search.py
def __init__(  # noqa: PLR0913
    self,
    data_dir: Path | str | None = None,
    framenet: FrameNetSearch | None = None,
    verbnet: VerbNetSearch | None = None,
    wordnet: WordNetSearch | None = None,
    propbank: PropBankSearch | None = None,
    auto_load: bool = True,
) -> None:
    """Initialize unified search.

    Parameters
    ----------
    data_dir : Path | str | None, optional
        Directory containing converted data files.
        If None, uses default path from environment.
    framenet : FrameNetSearch | None, optional
        Pre-initialized FrameNet search object.
    verbnet : VerbNetSearch | None, optional
        Pre-initialized VerbNet search object.
    wordnet : WordNetSearch | None, optional
        Pre-initialized WordNet search object.
    propbank : PropBankSearch | None, optional
        Pre-initialized PropBank search object.
    auto_load : bool, default=True
        If True and no search objects provided, automatically
        loads from data_dir.
    """
    # If auto_load and no search objects provided, load from default paths
    if auto_load and not any([framenet, verbnet, wordnet, propbank]):
        if data_dir is None:
            data_dir = get_default_data_path()
        data_dir = Path(data_dir)

        # Try to load each dataset if file exists
        if (data_dir / "framenet.jsonl").exists():
            fn_loader = FrameNetLoader()  # autoload=True by default
            framenet = FrameNetSearch(fn_loader.frames)
        if (data_dir / "verbnet.jsonl").exists():
            vn_loader = VerbNetLoader()  # autoload=True by default
            verbnet = VerbNetSearch(list(vn_loader.classes.values()))
        if (data_dir / "wordnet.jsonl").exists():
            wn_loader = WordNetLoader()  # autoload=True by default
            wordnet = WordNetSearch(list(wn_loader.synsets.values()))
        if (data_dir / "propbank.jsonl").exists():
            pb_loader = PropBankLoader()  # autoload=True by default
            propbank = PropBankSearch(list(pb_loader.framesets.values()))

    self.framenet = framenet
    self.verbnet = verbnet
    self.wordnet = wordnet
    self.propbank = propbank
    self._syntax_parser = SyntaxParser()
Functions
batch_by_lemma(lemmas: list[str], pos: str | None = None) -> dict[str, UnifiedSearchResult]

Search all datasets for multiple lemmas.

PARAMETER DESCRIPTION
lemmas

List of lemmas to search for.

TYPE: list[str]

pos

Part of speech constraint.

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
dict[str, UnifiedSearchResult]

Results mapped by lemma.

Source code in src/glazing/search.py
def batch_by_lemma(
    self, lemmas: list[str], pos: str | None = None
) -> dict[str, UnifiedSearchResult]:
    """Search all datasets for multiple lemmas.

    Parameters
    ----------
    lemmas : list[str]
        List of lemmas to search for.
    pos : str | None
        Part of speech constraint.

    Returns
    -------
    dict[str, UnifiedSearchResult]
        Results mapped by lemma.
    """
    results = {}
    for lemma in lemmas:
        results[lemma] = self.by_lemma(lemma, pos)
    return results
by_domain(domain: str) -> UnifiedSearchResult

Search within a specific domain.

PARAMETER DESCRIPTION
domain

Domain name (WordNet lexical file name).

TYPE: str

RETURNS DESCRIPTION
UnifiedSearchResult

Results from datasets that support domain search.

Source code in src/glazing/search.py
def by_domain(self, domain: str) -> UnifiedSearchResult:
    """Search within a specific domain.

    Parameters
    ----------
    domain : str
        Domain name (WordNet lexical file name).

    Returns
    -------
    UnifiedSearchResult
        Results from datasets that support domain search.
    """
    synsets = []

    # Only WordNet has explicit domains (lexical files)
    if self.wordnet:
        synsets = self.wordnet.by_domain(domain)  # type: ignore[arg-type]

    return UnifiedSearchResult(
        frames=[],
        verb_classes=[],
        synsets=synsets,
        framesets=[],
        rolesets=[],
    )
by_external_resource(resource_type: ResourceType, class_name: str | None = None) -> UnifiedSearchResult

Search for entries linked to external resources.

PARAMETER DESCRIPTION
resource_type

Type of resource (e.g., "VerbNet", "FrameNet").

TYPE: ResourceType

class_name

Specific class/frame name to match.

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
UnifiedSearchResult

Results from datasets with links to the resource.

Source code in src/glazing/search.py
def by_external_resource(
    self, resource_type: ResourceType, class_name: str | None = None
) -> UnifiedSearchResult:
    """Search for entries linked to external resources.

    Parameters
    ----------
    resource_type : ResourceType
        Type of resource (e.g., "VerbNet", "FrameNet").
    class_name : str | None
        Specific class/frame name to match.

    Returns
    -------
    UnifiedSearchResult
        Results from datasets with links to the resource.
    """
    rolesets = []

    # PropBank has external resource links
    if self.propbank:
        rolesets = self.propbank.by_resource(resource_type, class_name)

    return UnifiedSearchResult(
        frames=[],
        verb_classes=[],
        synsets=[],
        framesets=[],
        rolesets=rolesets,
    )
by_lemma(lemma: str, pos: str | None = None) -> UnifiedSearchResult

Search all datasets by lemma.

PARAMETER DESCRIPTION
lemma

Lemma to search for.

TYPE: str

pos

Part of speech constraint (format varies by dataset).

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
UnifiedSearchResult

Results from all datasets.

Source code in src/glazing/search.py
def by_lemma(self, lemma: str, pos: str | None = None) -> UnifiedSearchResult:
    """Search all datasets by lemma.

    Parameters
    ----------
    lemma : str
        Lemma to search for.
    pos : str | None
        Part of speech constraint (format varies by dataset).

    Returns
    -------
    UnifiedSearchResult
        Results from all datasets.
    """
    frames = self._search_framenet_by_lemma(lemma, pos)
    verb_classes = self._search_verbnet_by_lemma(lemma)
    synsets = self._search_wordnet_by_lemma(lemma, pos)
    framesets, rolesets = self._search_propbank_by_lemma(lemma)

    return UnifiedSearchResult(
        frames=frames,
        verb_classes=verb_classes,
        synsets=synsets,
        framesets=framesets,
        rolesets=rolesets,
    )
by_semantic_predicate(predicate: PredicateType) -> UnifiedSearchResult

Search for verb classes with a semantic predicate.

PARAMETER DESCRIPTION
predicate

Semantic predicate to search for.

TYPE: PredicateType

RETURNS DESCRIPTION
UnifiedSearchResult

Results from VerbNet.

Source code in src/glazing/search.py
def by_semantic_predicate(self, predicate: PredicateType) -> UnifiedSearchResult:
    """Search for verb classes with a semantic predicate.

    Parameters
    ----------
    predicate : PredicateType
        Semantic predicate to search for.

    Returns
    -------
    UnifiedSearchResult
        Results from VerbNet.
    """
    verb_classes = []

    # Only VerbNet has semantic predicates
    if self.verbnet:
        verb_classes = self.verbnet.by_predicate(predicate)

    return UnifiedSearchResult(
        frames=[],
        verb_classes=verb_classes,
        synsets=[],
        framesets=[],
        rolesets=[],
    )
by_semantic_role(role_name: str) -> UnifiedSearchResult

Search for frames/classes with a semantic role.

PARAMETER DESCRIPTION
role_name

Name of semantic role (e.g., "Agent", "Theme").

TYPE: str

RETURNS DESCRIPTION
UnifiedSearchResult

Results from datasets that have this role.

Source code in src/glazing/search.py
def by_semantic_role(self, role_name: str) -> UnifiedSearchResult:
    """Search for frames/classes with a semantic role.

    Parameters
    ----------
    role_name : str
        Name of semantic role (e.g., "Agent", "Theme").

    Returns
    -------
    UnifiedSearchResult
        Results from datasets that have this role.
    """
    frames = []
    verb_classes = []

    # Search FrameNet for frames with this FE
    if self.framenet:
        frames = self.framenet.find_frames_with_fe(role_name)

    # Search VerbNet for classes with this thematic role
    if self.verbnet:
        # Cast role_name to ThematicRoleType if it matches a valid role
        try:
            verb_classes = self.verbnet.by_themroles([role_name])  # type: ignore[list-item]
        except (ValueError, KeyError):
            verb_classes = []

    # PropBank uses numbered arguments, not named roles
    # WordNet doesn't have semantic roles

    return UnifiedSearchResult(
        frames=frames,
        verb_classes=verb_classes,
        synsets=[],
        framesets=[],
        rolesets=[],
    )
find_cross_references(entity_id: str, source: str, target: str) -> list[dict[str, str | float]]

Find cross-references between datasets.

PARAMETER DESCRIPTION
entity_id

Source entity identifier.

TYPE: str

source

Source dataset name.

TYPE: str

target

Target dataset name.

TYPE: str

RETURNS DESCRIPTION
list[dict]

List of cross-reference mappings.

Source code in src/glazing/search.py
def find_cross_references(
    self, entity_id: str, source: str, target: str
) -> list[dict[str, str | float]]:
    """Find cross-references between datasets.

    Parameters
    ----------
    entity_id : str
        Source entity identifier.
    source : str
        Source dataset name.
    target : str
        Target dataset name.

    Returns
    -------
    list[dict]
        List of cross-reference mappings.
    """
    mapping_strategies = {
        ("verbnet", "propbank"): self._verbnet_to_propbank_refs,
        ("propbank", "verbnet"): self._propbank_to_verbnet_refs,
        ("verbnet", "framenet"): self._verbnet_to_framenet_refs,
        ("framenet", "verbnet"): self._framenet_to_verbnet_refs,
        ("propbank", "framenet"): self._propbank_to_framenet_refs,
    }

    # Handle WordNet to other datasets
    if source == "wordnet" and target in ["verbnet", "propbank", "framenet"]:
        return self._wordnet_to_other_refs(entity_id, target)

    strategy = mapping_strategies.get((source, target))
    return strategy(entity_id) if strategy else []
from_paths(framenet_path: Path | str | None = None, verbnet_path: Path | str | None = None, wordnet_synsets_path: Path | str | None = None, wordnet_senses_path: Path | str | None = None, propbank_path: Path | str | None = None) -> UnifiedSearch classmethod

Load unified search from JSON Lines files.

PARAMETER DESCRIPTION
framenet_path

Path to FrameNet JSONL file.

TYPE: Path | str | None DEFAULT: None

verbnet_path

Path to VerbNet JSONL file.

TYPE: Path | str | None DEFAULT: None

wordnet_synsets_path

Path to WordNet synsets JSONL file.

TYPE: Path | str | None DEFAULT: None

wordnet_senses_path

Path to WordNet senses JSONL file.

TYPE: Path | str | None DEFAULT: None

propbank_path

Path to PropBank JSONL file.

TYPE: Path | str | None DEFAULT: None

RETURNS DESCRIPTION
UnifiedSearch

Unified search with loaded datasets.

Source code in src/glazing/search.py
@classmethod
def from_paths(
    cls,
    framenet_path: Path | str | None = None,
    verbnet_path: Path | str | None = None,
    wordnet_synsets_path: Path | str | None = None,
    wordnet_senses_path: Path | str | None = None,
    propbank_path: Path | str | None = None,
) -> UnifiedSearch:
    """Load unified search from JSON Lines files.

    Parameters
    ----------
    framenet_path : Path | str | None
        Path to FrameNet JSONL file.
    verbnet_path : Path | str | None
        Path to VerbNet JSONL file.
    wordnet_synsets_path : Path | str | None
        Path to WordNet synsets JSONL file.
    wordnet_senses_path : Path | str | None
        Path to WordNet senses JSONL file.
    propbank_path : Path | str | None
        Path to PropBank JSONL file.

    Returns
    -------
    UnifiedSearch
        Unified search with loaded datasets.
    """
    framenet = None
    if framenet_path:
        framenet = FrameNetSearch.from_jsonl_file(framenet_path)

    verbnet = None
    if verbnet_path:
        verbnet = VerbNetSearch.from_jsonl_file(verbnet_path)

    wordnet = None
    if wordnet_synsets_path or wordnet_senses_path:
        wordnet = WordNetSearch.from_jsonl_files(
            synsets_path=wordnet_synsets_path,
            senses_path=wordnet_senses_path,
        )

    propbank = None
    if propbank_path:
        propbank = PropBankSearch.from_jsonl_file(propbank_path)

    return cls(
        framenet=framenet,
        verbnet=verbnet,
        wordnet=wordnet,
        propbank=propbank,
    )
get_entity(entity_id: str, dataset: str) -> Frame | VerbClass | Synset | Frameset | None

Get a specific entity from a dataset.

PARAMETER DESCRIPTION
entity_id

Entity identifier.

TYPE: str

dataset

Dataset name.

TYPE: str

RETURNS DESCRIPTION
Frame | VerbClass | Synset | Frameset | None

The entity if found, None otherwise.

Source code in src/glazing/search.py
def get_entity(
    self, entity_id: str, dataset: str
) -> Frame | VerbClass | Synset | Frameset | None:
    """Get a specific entity from a dataset.

    Parameters
    ----------
    entity_id : str
        Entity identifier.
    dataset : str
        Dataset name.

    Returns
    -------
    Frame | VerbClass | Synset | Frameset | None
        The entity if found, None otherwise.
    """
    if dataset == "framenet" and self.framenet:
        return self.framenet.get_frame_by_name(entity_id)
    if dataset == "verbnet" and self.verbnet:
        # VerbNet searches by ID
        return self.verbnet.get_by_id(entity_id)
    if dataset == "wordnet" and self.wordnet:
        # WordNet ID format: offset+pos (e.g., "01234567n")
        return self.wordnet.get_synset_by_id(entity_id)
    if dataset == "propbank" and self.propbank:
        return self.propbank.by_lemma(entity_id)
    return None
get_statistics() -> dict[str, dict[str, int]]

Get statistics across all datasets.

RETURNS DESCRIPTION
dict[str, dict[str, int]]

Statistics for each available dataset.

Source code in src/glazing/search.py
def get_statistics(self) -> dict[str, dict[str, int]]:
    """Get statistics across all datasets.

    Returns
    -------
    dict[str, dict[str, int]]
        Statistics for each available dataset.
    """
    stats = {}

    if self.framenet:
        stats["framenet"] = self.framenet.get_statistics()

    if self.verbnet:
        stats["verbnet"] = self.verbnet.get_statistics()

    if self.wordnet:
        stats["wordnet"] = self.wordnet.get_statistics()

    if self.propbank:
        stats["propbank"] = self.propbank.get_statistics()

    return stats
load_framenet_from_jsonl(filepath: str) -> None

Load FrameNet data from JSONL file.

Source code in src/glazing/search.py
def load_framenet_from_jsonl(self, filepath: str) -> None:
    """Load FrameNet data from JSONL file."""
    frames = []
    with Path(filepath).open(encoding="utf-8") as f:
        for line in f:
            if line.strip():
                frames.append(Frame.model_validate_json(line))
    self.framenet = FrameNetSearch(frames)
load_propbank_from_jsonl(filepath: str) -> None

Load PropBank data from JSONL file.

Source code in src/glazing/search.py
def load_propbank_from_jsonl(self, filepath: str) -> None:
    """Load PropBank data from JSONL file."""
    framesets = []
    with Path(filepath).open(encoding="utf-8") as f:
        for line in f:
            if line.strip():
                framesets.append(Frameset.model_validate_json(line))
    self.propbank = PropBankSearch(framesets)
load_verbnet_from_jsonl(filepath: str) -> None

Load VerbNet data from JSONL file.

Source code in src/glazing/search.py
def load_verbnet_from_jsonl(self, filepath: str) -> None:
    """Load VerbNet data from JSONL file."""
    verb_classes = []
    with Path(filepath).open(encoding="utf-8") as f:
        for line in f:
            if line.strip():
                verb_classes.append(VerbClass.model_validate_json(line))
    self.verbnet = VerbNetSearch(verb_classes)
load_wordnet_from_jsonl(synsets_path: str, _index_path: str, _pos: str) -> None

Load WordNet data from JSONL files.

Source code in src/glazing/search.py
def load_wordnet_from_jsonl(self, synsets_path: str, _index_path: str, _pos: str) -> None:
    """Load WordNet data from JSONL files."""
    synsets = []
    with Path(synsets_path).open(encoding="utf-8") as f:
        for line in f:
            if line.strip():
                synsets.append(Synset.model_validate_json(line))

    # Initialize or merge with existing WordNet search
    if self.wordnet is None:
        self.wordnet = WordNetSearch(synsets)
    else:
        # Merge synsets with existing ones
        existing_synsets = self.wordnet.get_all_synsets()
        # Create a dict to merge by offset to avoid duplicates
        synset_dict = {f"{s.offset:08d}{s.ss_type}": s for s in existing_synsets}
        for synset in synsets:
            synset_id = f"{synset.offset:08d}{synset.ss_type}"
            synset_dict[synset_id] = synset
        # Recreate WordNetSearch with merged synsets
        self.wordnet = WordNetSearch(list(synset_dict.values()))
search(query: str) -> list[SearchResult]

Search across all datasets with a text query.

PARAMETER DESCRIPTION
query

Search query text.

TYPE: str

RETURNS DESCRIPTION
list[SearchResult]

List of search results across all datasets.

Source code in src/glazing/search.py
def search(self, query: str) -> list[SearchResult]:
    """Search across all datasets with a text query.

    Parameters
    ----------
    query : str
        Search query text.

    Returns
    -------
    list[SearchResult]
        List of search results across all datasets.
    """
    results = []

    # Search each dataset and convert to SearchResult format
    if self.framenet:
        frames = self.framenet.find_frames_by_lemma(query)
        for frame in frames:
            results.append(
                SearchResult(
                    dataset="framenet",
                    id=frame.name,
                    type="frame",
                    name=frame.name,
                    description=frame.definition.plain_text if frame.definition else "",
                    score=1.0,
                )
            )

    if self.verbnet:
        classes = self.verbnet.by_members([query])
        for cls in classes:
            results.append(
                SearchResult(
                    dataset="verbnet",
                    id=cls.id,
                    type="class",
                    name=cls.id,
                    description=f"VerbNet class with {len(cls.members)} members",
                    score=1.0,
                )
            )

    if self.wordnet:
        synsets = self.wordnet.by_lemma(query)
        for synset in synsets:
            synset_id = f"{synset.offset:08d}{synset.ss_type}"
            results.append(
                SearchResult(
                    dataset="wordnet",
                    id=synset_id,
                    type="synset",
                    name=synset_id,
                    description=synset.gloss or "",
                    score=1.0,
                )
            )

    if self.propbank:
        frameset = self.propbank.by_lemma(query)
        if frameset:
            results.append(
                SearchResult(
                    dataset="propbank",
                    id=frameset.predicate_lemma,
                    type="frameset",
                    name=frameset.predicate_lemma,
                    description=f"PropBank frameset with {len(frameset.rolesets)} rolesets",
                    score=1.0,
                )
            )

    return results
search_by_syntax(pattern: str, dataset: str | None = None, allow_wildcards: bool = True, min_confidence: float = 0.7) -> list[SearchResult]

Search by syntactic pattern with hierarchical matching.

General patterns match specific instances with full confidence.

PARAMETER DESCRIPTION
pattern

Syntactic pattern with optional wildcards and roles. Examples: - "NP V NP" - basic transitive - "NP V PP" - matches all PP subtypes - "NP V PP.instrument" - specific PP role - "NP V NP *" - wildcard for fourth position

TYPE: str

dataset

Limit to specific dataset (verbnet, propbank, framenet).

TYPE: str | None DEFAULT: None

allow_wildcards

Whether to process wildcard elements (*).

TYPE: bool DEFAULT: True

min_confidence

Minimum confidence score for matches (0.0-1.0).

TYPE: float DEFAULT: 0.7

RETURNS DESCRIPTION
list[SearchResult]

Matching results sorted by confidence.

Examples:

>>> search = UnifiedSearch()
>>> # Find all PP patterns
>>> results = search.search_by_syntax("NP V PP")
>>> # Find specific PP role
>>> results = search.search_by_syntax("NP V PP.instrument")
>>> # Use wildcards
>>> results = search.search_by_syntax("NP V NP *")
Source code in src/glazing/search.py
def search_by_syntax(
    self,
    pattern: str,
    dataset: str | None = None,
    allow_wildcards: bool = True,
    min_confidence: float = 0.7,
) -> list[SearchResult]:
    """Search by syntactic pattern with hierarchical matching.

    General patterns match specific instances with full confidence.

    Parameters
    ----------
    pattern : str
        Syntactic pattern with optional wildcards and roles.
        Examples:
        - "NP V NP" - basic transitive
        - "NP V PP" - matches all PP subtypes
        - "NP V PP.instrument" - specific PP role
        - "NP V NP *" - wildcard for fourth position

    dataset : str | None
        Limit to specific dataset (verbnet, propbank, framenet).

    allow_wildcards : bool
        Whether to process wildcard elements (*).

    min_confidence : float
        Minimum confidence score for matches (0.0-1.0).

    Returns
    -------
    list[SearchResult]
        Matching results sorted by confidence.

    Examples
    --------
    >>> search = UnifiedSearch()
    >>> # Find all PP patterns
    >>> results = search.search_by_syntax("NP V PP")
    >>> # Find specific PP role
    >>> results = search.search_by_syntax("NP V PP.instrument")
    >>> # Use wildcards
    >>> results = search.search_by_syntax("NP V NP *")
    """
    query_pattern = self._syntax_parser.parse(pattern)
    results: list[SearchResult] = []

    self._search_verbnet_syntax(
        results, query_pattern, dataset, allow_wildcards, min_confidence
    )
    self._search_propbank_syntax(results, pattern, dataset)
    self._search_framenet_syntax(results, pattern, dataset)
    self._search_wordnet_syntax(results, pattern, dataset)

    # Sort by confidence score
    results.sort(key=lambda r: r.score, reverse=True)
    return results
search_framenet_elements(core_type: str | None = None, semantic_type: str | None = None) -> list[Frame]

Search FrameNet frames by element properties.

PARAMETER DESCRIPTION
core_type

"Core", "Non-Core", or "Extra-Thematic".

TYPE: str | None DEFAULT: None

semantic_type

Semantic type of elements.

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
list[Frame]

FrameNet frames matching criteria.

Source code in src/glazing/search.py
def search_framenet_elements(
    self, core_type: str | None = None, semantic_type: str | None = None
) -> list[Frame]:
    """Search FrameNet frames by element properties.

    Parameters
    ----------
    core_type : str | None, optional
        "Core", "Non-Core", or "Extra-Thematic".
    semantic_type : str | None, optional
        Semantic type of elements.

    Returns
    -------
    list[Frame]
        FrameNet frames matching criteria.
    """
    if not self.framenet:
        return []

    matching_frames = []
    for frame in self.framenet._frames_by_id.values():
        filtered_elements = filter_elements_by_properties(
            frame.frame_elements,
            core_type=core_type,  # type: ignore[arg-type]
        )
        # Additional filtering for semantic_type if needed
        if semantic_type and filtered_elements:
            filtered_elements = [
                e
                for e in filtered_elements
                if hasattr(e, "semantic_type") and e.semantic_type == semantic_type
            ]
        if filtered_elements:
            matching_frames.append(frame)

    return matching_frames
search_propbank_args(arg_type: str | None = None, prefix: str | None = None, modifier: str | None = None, arg_number: str | None = None) -> list[Roleset]

Search PropBank rolesets by argument properties.

PARAMETER DESCRIPTION
arg_type

"core" or "modifier".

TYPE: str | None DEFAULT: None

prefix

"C" or "R" for continuation/reference.

TYPE: str | None DEFAULT: None

modifier

Modifier type (e.g., "LOC", "TMP").

TYPE: str | None DEFAULT: None

arg_number

Specific argument number (e.g., "0", "1", "2").

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
list[Roleset]

PropBank rolesets matching criteria.

Source code in src/glazing/search.py
def search_propbank_args(
    self,
    arg_type: str | None = None,
    prefix: str | None = None,
    modifier: str | None = None,
    arg_number: str | None = None,
) -> list[Roleset]:
    """Search PropBank rolesets by argument properties.

    Parameters
    ----------
    arg_type : str | None, optional
        "core" or "modifier".
    prefix : str | None, optional
        "C" or "R" for continuation/reference.
    modifier : str | None, optional
        Modifier type (e.g., "LOC", "TMP").
    arg_number : str | None, optional
        Specific argument number (e.g., "0", "1", "2").

    Returns
    -------
    list[Roleset]
        PropBank rolesets matching criteria.
    """
    if not self.propbank:
        return []

    matching_rolesets = []
    for frameset in self.propbank.get_all_framesets():
        for roleset in frameset.rolesets:
            filtered_args = filter_args_by_properties(
                roleset.roles,
                is_core=(arg_type == "core") if arg_type else None,
                modifier_type=modifier.lower() if modifier else None,  # type: ignore[arg-type]
                has_prefix=True if prefix in ["C", "R"] else None,
                arg_number=arg_number,
            )
            if filtered_args:
                matching_rolesets.append(roleset)

    return matching_rolesets
search_semantic_roles(role_name: str) -> list[SearchResult]

Search for semantic roles across datasets.

PARAMETER DESCRIPTION
role_name

Role name to search for.

TYPE: str

RETURNS DESCRIPTION
list[SearchResult]

List of search results for the role.

Source code in src/glazing/search.py
def search_semantic_roles(self, role_name: str) -> list[SearchResult]:
    """Search for semantic roles across datasets.

    Parameters
    ----------
    role_name : str
        Role name to search for.

    Returns
    -------
    list[SearchResult]
        List of search results for the role.
    """
    results = []

    # Search FrameNet for frame elements
    if self.framenet:
        frames = self.framenet.find_frames_with_fe(role_name)
        for frame in frames:
            results.append(
                SearchResult(
                    dataset="framenet",
                    id=frame.name,
                    type="frame_element",
                    name=frame.name,
                    description=f"Frame with {role_name} element",
                    score=1.0,
                )
            )

    # Search VerbNet for thematic roles
    if self.verbnet:
        # Search for classes with this thematic role
        # Cast role_name to ThematicRoleType if it matches a valid role
        try:
            classes = self.verbnet.by_themroles([role_name])  # type: ignore[list-item]
        except (ValueError, KeyError):
            classes = []
        for cls in classes:
            results.append(
                SearchResult(
                    dataset="verbnet",
                    id=cls.id,
                    type="thematic_role",
                    name=cls.id,
                    description=f"Class with {role_name} role",
                    score=1.0,
                )
            )

    return results
search_verbnet_roles(optional: bool | None = None, indexed: bool | None = None, verb_specific: bool | None = None) -> list[VerbClass]

Search VerbNet classes by role properties.

PARAMETER DESCRIPTION
optional

Filter for optional roles.

TYPE: bool | None DEFAULT: None

indexed

Filter for indexed roles.

TYPE: bool | None DEFAULT: None

verb_specific

Filter for verb-specific roles.

TYPE: bool | None DEFAULT: None

RETURNS DESCRIPTION
list[VerbClass]

VerbNet classes matching criteria.

Source code in src/glazing/search.py
def search_verbnet_roles(
    self,
    optional: bool | None = None,
    indexed: bool | None = None,
    verb_specific: bool | None = None,
) -> list[VerbClass]:
    """Search VerbNet classes by role properties.

    Parameters
    ----------
    optional : bool | None, optional
        Filter for optional roles.
    indexed : bool | None, optional
        Filter for indexed roles.
    verb_specific : bool | None, optional
        Filter for verb-specific roles.

    Returns
    -------
    list[VerbClass]
        VerbNet classes matching criteria.
    """
    if not self.verbnet:
        return []

    matching_classes = []
    for cls in self.verbnet.get_all_classes():
        filtered_roles = filter_roles_by_properties(
            cls.themroles,
            optional=optional,
            indexed=indexed,
            verb_specific=verb_specific,
        )
        if filtered_roles:
            matching_classes.append(cls)

    return matching_classes
search_with_fuzzy(query: str, fuzzy_threshold: float = 0.8) -> list[SearchResult]

Search across all datasets with fuzzy matching.

PARAMETER DESCRIPTION
query

Search query text.

TYPE: str

fuzzy_threshold

Minimum similarity score for fuzzy matches.

TYPE: float DEFAULT: 0.8

RETURNS DESCRIPTION
list[SearchResult]

Search results with confidence scores.

Source code in src/glazing/search.py
def search_with_fuzzy(  # noqa: C901, PLR0912
    self, query: str, fuzzy_threshold: float = 0.8
) -> list[SearchResult]:
    """Search across all datasets with fuzzy matching.

    Parameters
    ----------
    query : str
        Search query text.
    fuzzy_threshold : float, default=0.8
        Minimum similarity score for fuzzy matches.

    Returns
    -------
    list[SearchResult]
        Search results with confidence scores.
    """
    results = []
    query_normalized = query.lower()

    # Search each dataset with fuzzy matching
    if self.framenet:
        for frame in self.framenet._frames_by_id.values():
            similarity = levenshtein_ratio(query_normalized, frame.name.lower())
            if similarity >= fuzzy_threshold:
                results.append(
                    SearchResult(
                        dataset="framenet",
                        id=frame.name,
                        type="frame",
                        name=frame.name,
                        description=frame.definition.plain_text if frame.definition else "",
                        score=similarity,
                    )
                )

    if self.verbnet:
        for cls in self.verbnet.get_all_classes():
            for member in cls.members:
                similarity = levenshtein_ratio(query_normalized, member.name.lower())
                if similarity >= fuzzy_threshold:
                    results.append(
                        SearchResult(
                            dataset="verbnet",
                            id=cls.id,
                            type="class",
                            name=cls.id,
                            description=f"VerbNet class with member {member.name}",
                            score=similarity,
                        )
                    )
                    break  # Only add class once

    if self.wordnet:
        for synset in self.wordnet.get_all_synsets():
            for word in synset.words:
                similarity = levenshtein_ratio(query_normalized, word.lemma.lower())
                if similarity >= fuzzy_threshold:
                    synset_id = f"{synset.offset:08d}{synset.ss_type}"
                    results.append(
                        SearchResult(
                            dataset="wordnet",
                            id=synset_id,
                            type="synset",
                            name=synset_id,
                            description=synset.gloss or "",
                            score=similarity,
                        )
                    )
                    break  # Only add synset once

    if self.propbank:
        for frameset in self.propbank.get_all_framesets():
            similarity = levenshtein_ratio(query_normalized, frameset.predicate_lemma.lower())
            if similarity >= fuzzy_threshold:
                results.append(
                    SearchResult(
                        dataset="propbank",
                        id=frameset.predicate_lemma,
                        type="frameset",
                        name=frameset.predicate_lemma,
                        description=f"PropBank frameset with {len(frameset.rolesets)} rolesets",
                        score=similarity,
                    )
                )

    # Sort by score
    results.sort(key=lambda r: r.score, reverse=True)
    return results
search_wordnet_relations(relation_type: str | None = None) -> list[Synset]

Search WordNet synsets by relation type.

PARAMETER DESCRIPTION
relation_type

Relation type (e.g., "hypernym", "hyponym").

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
list[Synset]

WordNet synsets with specified relations.

Source code in src/glazing/search.py
def search_wordnet_relations(self, relation_type: str | None = None) -> list[Synset]:
    """Search WordNet synsets by relation type.

    Parameters
    ----------
    relation_type : str | None, optional
        Relation type (e.g., "hypernym", "hyponym").

    Returns
    -------
    list[Synset]
        WordNet synsets with specified relations.
    """
    if not self.wordnet:
        return []

    matching_synsets = []
    for synset in self.wordnet.get_all_synsets():
        filtered_ptrs = filter_by_relation_type(synset.pointers, relation_type)
        if filtered_ptrs:
            matching_synsets.append(synset)

    return matching_synsets

UnifiedSearchResult(frames: list[Frame], verb_classes: list[VerbClass], synsets: list[Synset], framesets: list[Frameset], rolesets: list[Roleset]) dataclass

Container for search results across all datasets.

PARAMETER DESCRIPTION
frames

FrameNet frames found.

TYPE: list[Frame]

verb_classes

VerbNet verb classes found.

TYPE: list[VerbClass]

synsets

WordNet synsets found.

TYPE: list[Synset]

framesets

PropBank framesets found.

TYPE: list[Frameset]

rolesets

PropBank rolesets found.

TYPE: list[Roleset]

Examples:

>>> result = UnifiedSearchResult(
...     frames=[giving_frame],
...     verb_classes=[give_class],
...     synsets=[give_synset],
...     framesets=[give_frameset],
...     rolesets=[]
... )
METHOD DESCRIPTION
count

Get total count of all results.

is_empty

Check if all result lists are empty.

Functions
count() -> int

Get total count of all results.

RETURNS DESCRIPTION
int

Total number of results across all datasets.

Source code in src/glazing/search.py
def count(self) -> int:
    """Get total count of all results.

    Returns
    -------
    int
        Total number of results across all datasets.
    """
    return (
        len(self.frames)
        + len(self.verb_classes)
        + len(self.synsets)
        + len(self.framesets)
        + len(self.rolesets)
    )
is_empty() -> bool

Check if all result lists are empty.

RETURNS DESCRIPTION
bool

True if no results found in any dataset.

Source code in src/glazing/search.py
def is_empty(self) -> bool:
    """Check if all result lists are empty.

    Returns
    -------
    bool
        True if no results found in any dataset.
    """
    return not any(
        [
            self.frames,
            self.verb_classes,
            self.synsets,
            self.framesets,
            self.rolesets,
        ]
    )

Functions