def find_item_suggestions( name, modaliases, schema, *, item_types=None, limit=3, collection=None, condition=None): from . import modules as s_mod if isinstance(name, sn.Name): orig_modname = name.module short_name = name.name else: orig_modname = None short_name = name modname = modaliases.get(orig_modname, orig_modname) suggestions = [] if collection is not None: suggestions.extend(collection) else: if modname: module = schema.get_global(s_mod.Module, modname, None) if module: suggestions.extend(schema.get_objects(modules=[modname])) if not orig_modname: suggestions.extend(schema.get_objects(modules=['std'])) if item_types: suggestions = list( filter(lambda s: isinstance(s, item_types), suggestions)) if condition is not None: suggestions = list(filter(condition, suggestions)) # Compute Levenshtein distance for each suggestion. with_distance = [ (s, levenshtein.distance(short_name, get_nq_name(schema, s))) for s in suggestions ] # Filter out suggestions that are too dissimilar. max_distance = 3 closest = list(filter(lambda s: s[1] < max_distance, with_distance)) # Sort by proximity, then by whether the suggestion is contains # the source string at the beginning, then by suggestion name. closest.sort( key=lambda s: ( s[1], not get_nq_name(schema, s[0]).startswith(short_name), s[0].get_displayname(schema) ) ) return [s[0] for s in closest[:limit]]
def find_item_suggestions( name: Optional[str], modaliases: Mapping[Optional[str], str], schema: s_schema.Schema, *, item_types: Tuple[so.ObjectMeta, ...] = (), limit: int = 3, collection: Optional[Iterable[so.Object]] = None, condition: Optional[Callable[[so.Object], bool]] = None) -> List[so.Object]: from . import functions as s_func from . import modules as s_mod if isinstance(name, sn.Name): orig_modname: Optional[str] = name.module short_name: str = name.name else: assert name is not None, ("A name must be provided either " "as string or SchemaName") orig_modname = None short_name = name modname = modaliases.get(orig_modname, orig_modname) suggestions: List[so.Object] = [] if collection is not None: suggestions.extend(collection) else: if modname: module = schema.get_global(s_mod.Module, modname, None) if module: suggestions.extend( schema.get_objects(included_modules=[modname])) if not orig_modname: suggestions.extend(schema.get_objects(included_modules=['std'])) filters = [] if item_types: filters.append(lambda s: isinstance(s, item_types)) if condition is not None: filters.append(condition) if not item_types: # When schema class is not specified, only suggest generic objects. filters.append(lambda s: not sn.is_fullname(s.get_name(schema))) filters.append(lambda s: not isinstance(s, s_func.CallableObject)) # Never suggest object fragments. filters.append(lambda s: not isinstance(s, so.ObjectFragment)) filtered_suggestions = filter(lambda s: all(f(s) for f in filters), suggestions) # Compute Levenshtein distance for each suggestion. with_distance: List[Tuple[so.Object, int]] = [ (s, levenshtein.distance(short_name, get_nq_name(schema, s))) for s in filtered_suggestions ] # Filter out suggestions that are too dissimilar. max_distance = 3 closest = list(filter(lambda s: s[1] < max_distance, with_distance)) # Sort by proximity, then by whether the suggestion is contains # the source string at the beginning, then by suggestion name. closest.sort(key=lambda s: (s[1], not get_nq_name(schema, s[0]).startswith( short_name), s[0].get_displayname(schema))) return [s[0] for s in closest[:limit]]