diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0432a655..b0ba5a98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,14 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + - name: Upgrade pip + run: python -m pip install --upgrade pip==23.2 - name: Install LIT package with testing dependencies run: python -m pip install -e '.[test]' + - name: Debug dependency tree + run: | + python -m pip install pipdeptree + pipdeptree | grep decorator -A 5 || true - name: Test LIT run: pytest -v - name: Setup Node ${{ matrix.node-version }} diff --git a/lit_nlp/api/components.py b/lit_nlp/api/components.py index b1cdcff3..93de3f2e 100644 --- a/lit_nlp/api/components.py +++ b/lit_nlp/api/components.py @@ -137,7 +137,7 @@ def is_compatible(self, model: lit_model.Model, """True if the model and dataset support metric computation.""" for pred_spec in model.output_spec().values(): parent_key: Optional[str] = getattr(pred_spec, 'parent', None) - parent_spec: Optional[types.LitType] = dataset.spec().get(parent_key) + parent_spec: Optional[types.LitType] = dataset.spec().get(parent_key) # pyrefly: ignore[bad-argument-type] if self.is_field_compatible(pred_spec, parent_spec): return True return False diff --git a/lit_nlp/api/dataset.py b/lit_nlp/api/dataset.py index eb315891..9d3b75f7 100644 --- a/lit_nlp/api/dataset.py +++ b/lit_nlp/api/dataset.py @@ -236,7 +236,7 @@ def remap(self, field_map: Mapping[str, str]): """Return a copy of this dataset with some fields renamed.""" new_spec = utils.remap_dict(self.spec(), field_map) new_examples = [utils.remap_dict(ex, field_map) for ex in self.examples] - return Dataset(new_spec, new_examples, base=self) + return Dataset(new_spec, new_examples, base=self) # pyrefly: ignore[bad-argument-type] @staticmethod def lit_example_from_bytes(input_bytes: bytes) -> Optional[JsonDict]: @@ -273,7 +273,7 @@ def index_inputs( indexed.append( IndexedInput( data=types.MappingProxyType( - example | {INPUT_ID_FIELD: ex_id, INPUT_META_FIELD: ex_meta} + example | {INPUT_ID_FIELD: ex_id, INPUT_META_FIELD: ex_meta} # pyrefly: ignore[unsupported-operation] ), id=ex_id, meta=ex_meta, @@ -376,6 +376,7 @@ def load(self, path: str): new_dataset = base_dataset.load(path) if base_dataset else None if new_dataset is not None: + # pyrefly: ignore[missing-attribute] description = (f'{len(new_dataset)} examples from ' f'{path}\n{self._base.description()}') return IndexedDataset( @@ -438,7 +439,7 @@ def load_lit_format( **kw, ) else: - return Dataset(spec=spec, examples=examples, *args, **kw) + return Dataset(spec=spec, examples=examples, *args, **kw) # pyrefly: ignore[bad-argument-type] # TODO(b/202210900): Remove "NoneDataset" once the LIT front-end constructs its diff --git a/lit_nlp/api/layout.py b/lit_nlp/api/layout.py index b39a2eb7..db56ae9e 100644 --- a/lit_nlp/api/layout.py +++ b/lit_nlp/api/layout.py @@ -70,7 +70,7 @@ def __call__(self, **kw): # LINT.IfChange # TODO(lit-dev): consider making modules subclass this instead of LitModuleName. @attr.s(auto_attribs=True) -class ModuleConfig(dtypes.DataTuple): +class ModuleConfig(dtypes.DataTuple): # pyrefly: ignore[invalid-inheritance] module: Union[str, LitModuleName] requiredForTab: bool = False # TODO(b/172979677): support title, duplicateAsRow, numCols, @@ -88,7 +88,7 @@ class ModuleConfig(dtypes.DataTuple): @attr.s(auto_attribs=True) -class LayoutSettings(dtypes.DataTuple): +class LayoutSettings(dtypes.DataTuple): # pyrefly: ignore[invalid-inheritance] hideToolbar: bool = False mainHeight: int = 45 leftWidth: int = 50 @@ -96,7 +96,7 @@ class LayoutSettings(dtypes.DataTuple): @attr.s(auto_attribs=True) -class LitCanonicalLayout(dtypes.DataTuple): +class LitCanonicalLayout(dtypes.DataTuple): # pyrefly: ignore[invalid-inheritance] """Frontend UI layout; should match client/lib/types.ts.""" upper: LitTabGroupLayout lower: LitTabGroupLayout = attr.ib(factory=dict) diff --git a/lit_nlp/api/model.py b/lit_nlp/api/model.py index 79558fce..32492b1e 100644 --- a/lit_nlp/api/model.py +++ b/lit_nlp/api/model.py @@ -178,12 +178,12 @@ def load(self, path: str): @abc.abstractmethod def input_spec(self) -> types.Spec: """Return a spec describing model inputs.""" - return + return # pyrefly: ignore[bad-return] @abc.abstractmethod def output_spec(self) -> types.Spec: """Return a spec describing model outputs.""" - return + return # pyrefly: ignore[bad-return] def get_embedding_table(self) -> tuple[list[str], np.ndarray]: """Return the full vocabulary and embedding table. @@ -369,7 +369,7 @@ def predict_minibatch(self, inputs: list[JsonDict]) -> list[JsonDict]: Returns: list of outputs, following model.output_spec() """ - return + return # pyrefly: ignore[bad-return] class ProjectorModel(BatchedModel, metaclass=abc.ABCMeta): diff --git a/lit_nlp/api/types.py b/lit_nlp/api/types.py index 3e7dbfd7..3851e0d3 100644 --- a/lit_nlp/api/types.py +++ b/lit_nlp/api/types.py @@ -155,10 +155,10 @@ def from_json(d: JsonDict): base_cls = globals().get("LitType") cls = globals().get(type_name) # class by name from this module - if cls is None or not issubclass(cls, base_cls): + if cls is None or not issubclass(cls, base_cls): # pyrefly: ignore[bad-argument-type] raise NameError(f"{type_name} is not a valid LitType.") - return cls(**{k: d[k] for k in d if k != "__name__"}) + return cls(**{k: d[k] for k in d if k != "__name__"}) # pyrefly: ignore[not-callable] Spec = dict[str, LitType] @@ -174,7 +174,7 @@ def _remap_leaf(leaf: LitType, keymap: dict[str, str]) -> LitType: k: (keymap.get(v, v) if k in FIELD_REF_ATTRIBUTES else v) for k, v in d.items() } - return leaf.__class__(**d) + return leaf.__class__(**d) # pyrefly: ignore[bad-argument-type] def remap_spec(spec: Spec, keymap: dict[str, str]) -> Spec: @@ -201,7 +201,7 @@ class StringLitType(LitType): Mainly used for string inputs that have special formatting, and should only be edited manually. """ - default: str = "" + default: str = "" # pyrefly: ignore[bad-override] def validate_input(self, value, spec: Spec, example: Input): if not isinstance(value, str): @@ -260,13 +260,13 @@ def validate_output(self, value, output_spec: Spec, output_dict: JsonDict, @attr.s(auto_attribs=True, frozen=True, kw_only=True) class ListLitType(LitType): """List type.""" - default: Sequence[Any] = None + default: Sequence[Any] = None # pyrefly: ignore[bad-assignment, bad-override] @attr.s(auto_attribs=True, frozen=True, kw_only=True) class _StringCandidateList(ListLitType): """A list of (text, score) tuples.""" - default: ScoredTextCandidates = None + default: ScoredTextCandidates = None # pyrefly: ignore[bad-assignment] def validate_output(self, value, output_spec: Spec, output_dict: JsonDict, input_spec: Spec, dataset_spec: Spec, @@ -373,9 +373,9 @@ class TokenTopKPreds(ListLitType): The inner list should contain (word, probability) in descending order. """ - default: Sequence[ScoredTextCandidates] = None + default: Sequence[ScoredTextCandidates] = None # pyrefly: ignore[bad-assignment] - align: str = None # name of a Tokens field in the model output + align: str = None # name of a Tokens field in the model output # pyrefly: ignore[bad-assignment] parent: Optional[str] = None def _validate_scored_candidates(self, scored_candidates): @@ -389,7 +389,7 @@ def _validate_scored_candidates(self, scored_candidates): if scored_candidate[1] is not None: if not isinstance(scored_candidate[1], NumericTypes): raise ValueError(f"{scored_candidate} second element is not a num") - if prev_val < scored_candidate[1]: + if prev_val < scored_candidate[1]: # pyrefly: ignore[unsupported-operation] raise ValueError( "TokenTopKPreds candidates are not in descending order") else: @@ -414,7 +414,7 @@ class Scalar(LitType): """Scalar value, a single float or int.""" min_val: float = 0 max_val: float = 1 - default: float = 0 + default: float = 0 # pyrefly: ignore[bad-override] step: float = .01 def validate_input(self, value, spec: Spec, example: Input): @@ -464,7 +464,7 @@ class TokenScores(_FloatList): @attr.s(auto_attribs=True, frozen=True, kw_only=True) class ReferenceScores(ListLitType): """Score of one or more target sequences.""" - default: Sequence[float] = None + default: Sequence[float] = None # pyrefly: ignore[bad-assignment] # name of a TextSegment or ReferenceTexts field in the input parent: Optional[str] = None @@ -504,7 +504,7 @@ def validate_input(self, value, spec: Spec, example: Input): @attr.s(auto_attribs=True, frozen=True, kw_only=True) class _Tensor(LitType): """A tensor type.""" - default: Sequence[float] = None + default: Sequence[float] = None # pyrefly: ignore[bad-assignment, bad-override] def validate_input(self, value, spec: Spec, example: Input): if isinstance(value, list): @@ -585,7 +585,7 @@ class SpanLabels(ListLitType): Span labels can cover more than one token, may not cover all tokens in the sentence, and may overlap with each other. """ - default: Sequence[dtypes.SpanLabel] = None + default: Sequence[dtypes.SpanLabel] = None # pyrefly: ignore[bad-assignment] align: str # name of Tokens field parent: Optional[str] = None @@ -609,7 +609,7 @@ class EdgeLabels(ListLitType): https://github.com/nyu-mll/jiant/tree/master/probing#data-format for more details. """ - default: Sequence[dtypes.EdgeLabel] = None + default: Sequence[dtypes.EdgeLabel] = None # pyrefly: ignore[bad-assignment] align: str # name of Tokens field def validate_output(self, value, output_spec: Spec, output_dict: JsonDict, @@ -636,7 +636,7 @@ class MultiSegmentAnnotations(ListLitType): TODO(lit-dev): by default, spans are treated as bytes in this context. Make this configurable, if some spans need to refer to tokens instead. """ - default: Sequence[dtypes.AnnotationCluster] = None + default: Sequence[dtypes.AnnotationCluster] = None # pyrefly: ignore[bad-assignment] exclusive: bool = False # if true, treat as candidate list background: bool = False # if true, don't emphasize in visualization @@ -775,7 +775,7 @@ class SubwordOffsets(ListLitType): offsets[i] should be the index of the first wordpiece for input token i. """ - default: Sequence[int] = None + default: Sequence[int] = None # pyrefly: ignore[bad-assignment] align_in: str # name of field in data spec align_out: str # name of field in model output spec @@ -793,7 +793,7 @@ class SparseMultilabelPreds(_StringCandidateList): The tuples are of the label and the score. """ - default: ScoredTextCandidates = None + default: ScoredTextCandidates = None # pyrefly: ignore[bad-assignment] vocab: Optional[Sequence[str]] = None # label names parent: Optional[str] = None @@ -816,7 +816,7 @@ class SingleFieldMatcher(FieldMatcher): UI will materialize this to a dropdown-list. """ - default: str = None + default: str = None # pyrefly: ignore[bad-assignment, bad-override] @attr.s(auto_attribs=True, frozen=True, kw_only=True) @@ -826,7 +826,7 @@ class MultiFieldMatcher(FieldMatcher): UI will materialize this to multiple checkboxes. Use this when the user needs to pick more than one field in UI. """ - default: Sequence[str] = [] # default names of selected items. + default: Sequence[str] = [] # default names of selected items. # pyrefly: ignore[bad-override] select_all: bool = False # Select all by default (overriddes default). @@ -840,20 +840,20 @@ class Salience(LitType): @attr.s(auto_attribs=True, frozen=True, kw_only=True) class TokenSalience(Salience): """Metadata about a returned token salience map.""" - default: dtypes.TokenSalience = None + default: dtypes.TokenSalience = None # pyrefly: ignore[bad-assignment, bad-override] @attr.s(auto_attribs=True, frozen=True, kw_only=True) class FeatureSalience(Salience): """Metadata about a returned feature salience map.""" - default: dtypes.FeatureSalience = None + default: dtypes.FeatureSalience = None # pyrefly: ignore[bad-assignment, bad-override] @attr.s(auto_attribs=True, frozen=True, kw_only=True) class FrameSalience(Salience): """Metadata about a returned frame salience map.""" - default: dtypes.FrameSalience = None + default: dtypes.FrameSalience = None # pyrefly: ignore[bad-assignment, bad-override] @attr.s(auto_attribs=True, frozen=True, kw_only=True) @@ -869,13 +869,13 @@ class ImageSalience(Salience): @attr.s(auto_attribs=True, frozen=True, kw_only=True) class SequenceSalience(Salience): """Metadata about a returned sequence salience map.""" - default: dtypes.SequenceSalienceMap = None + default: dtypes.SequenceSalienceMap = None # pyrefly: ignore[bad-assignment, bad-override] @attr.s(auto_attribs=True, frozen=True, kw_only=True) class BooleanLitType(LitType): """Boolean value.""" - default: bool = False + default: bool = False # pyrefly: ignore[bad-override] def validate_input(self, value, spec, example: Input): if not isinstance(value, bool): @@ -916,7 +916,7 @@ class MetricBestValue(dtypes.EnumSerializableAsValues, enum.Enum): @attr.s(auto_attribs=True, frozen=True, kw_only=True) class MetricResult(LitType): """Score returned from the computation of a Metric.""" - default: float = 0 + default: float = 0 # pyrefly: ignore[bad-override] description: str = "" best_value: MetricBestValue = MetricBestValue.NONE @@ -934,7 +934,7 @@ class SalienceTargetInfo(LitType): Value is a dict with keys 'field' (str) and 'index' (Optional[int]). """ - default: Optional[Mapping[str, Any]] = None + default: Optional[Mapping[str, Any]] = None # pyrefly: ignore[bad-override] # LINT.ThenChange(../client/lib/lit_types.ts) diff --git a/lit_nlp/app.py b/lit_nlp/app.py index 7d8afba5..2e773fae 100644 --- a/lit_nlp/app.py +++ b/lit_nlp/app.py @@ -111,7 +111,7 @@ def _build_metadata(self): } # List compatible datasets. - info['datasets'] = [ + info['datasets'] = [ # pyrefly: ignore[bad-assignment] name for name, dataset in self._datasets.items() if model.is_compatible_with_dataset(dataset) ] @@ -134,13 +134,13 @@ def _build_metadata(self): _get_compatible_names(self._metrics, model, dataset) ) - info['generators'] = [ + info['generators'] = [ # pyrefly: ignore[bad-assignment] name for name in self._generators.keys() if name in compat_gens ] - info['interpreters'] = [ + info['interpreters'] = [ # pyrefly: ignore[bad-assignment] name for name in self._interpreters.keys() if name in compat_interps ] - info['metrics'] = [ + info['metrics'] = [ # pyrefly: ignore[bad-assignment] name for name in self._metrics.keys() if name in compat_metrics ] model_info[name] = info @@ -213,7 +213,7 @@ def _reconstitute_inputs( len(inputs), dataset_name, ) - return [index[ex] if isinstance(ex, str) else ex for ex in inputs] + return [index[ex] if isinstance(ex, str) else ex for ex in inputs] # pyrefly: ignore[bad-index] def _save_datapoints( self, @@ -297,16 +297,16 @@ def _get_preds(self, # Figure out what to return to the frontend. output_spec = self._get_model_spec(model)['output'] - requested_types = requested_types.split(',') if requested_types else [] - requested_fields = requested_fields.split(',') if requested_fields else [] + requested_types = requested_types.split(',') if requested_types else [] # pyrefly: ignore[bad-assignment] + requested_fields = requested_fields.split(',') if requested_fields else [] # pyrefly: ignore[bad-assignment] logging.info('Requested types: %s, fields: %s', str(requested_types), str(requested_fields)) - for t_name in requested_types: + for t_name in requested_types: # pyrefly: ignore[not-iterable] t_class = getattr(types, t_name, None) - if not issubclass(t_class, types.LitType): + if not issubclass(t_class, types.LitType): # pyrefly: ignore[bad-argument-type] raise TypeError(f"Class '{t_name}' is not a valid LitType.") requested_fields.extend(utils.find_spec_keys(output_spec, t_class)) - ret_keys = set(requested_fields) # de-dupe + ret_keys = set(requested_fields) # de-dupe # pyrefly: ignore[bad-argument-type] # Return selected keys. logging.info('Will return keys: %s', str(ret_keys)) @@ -861,7 +861,7 @@ def _run_annotators(self, for annotator in self._annotators: annotator.annotate(datapoints, dataset, annotated_spec) return lit_dataset.Dataset( - base=dataset, examples=datapoints, spec=annotated_spec) + base=dataset, examples=datapoints, spec=annotated_spec) # pyrefly: ignore[bad-argument-type] def make_handler(self, fn): """Convenience wrapper to handle args and serialization. @@ -1009,9 +1009,9 @@ def __init__( # Interpreter initialization if interpreters is not None: - self._interpreters = core.required_interpreters() | interpreters + self._interpreters = core.required_interpreters() | interpreters # pyrefly: ignore[unsupported-operation] else: - self._interpreters = core.default_interpreters(self._models) + self._interpreters = core.default_interpreters(self._models) # pyrefly: ignore[bad-argument-type] if metrics is not None: self._metrics = metrics diff --git a/lit_nlp/client/core/slice_module.ts b/lit_nlp/client/core/slice_module.ts index 674e652a..43b454b5 100644 --- a/lit_nlp/client/core/slice_module.ts +++ b/lit_nlp/client/core/slice_module.ts @@ -160,7 +160,7 @@ export class SliceModule extends LitModule { // clang-format off return html`
- {onKeyUp(e);}}/>