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);}}/>