Error: "Local variable "x" has inferred type None; add an annotation", while annotation seems to be provided.
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 20.6k
- Fork
- 3.3k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
Bug Report
(A clear and concise description of what the bug is.)
mypyc complains about error: Local variable "x" has inferred type None; add an annotation, while it seems to me, that the annotation is added. mypy doesn't complain about it at all.
To Reproduce
git clone ---depth 1 https://github.com/pola-rs/polars
cd polars/py-polars
$ mypyc polars/utils/_construction.py
polars/utils/_construction.py:1050: error: Local variable "orient" has inferred type None; add an annotation
polars/utils/_construction.py:1248: error: Local variable "schema" has inferred type None; add an annotation
$ mypy polars/utils/_construction.py
Success: no issues found in 1 source file
$ tail -n +1046 polars/utils/_construction.py | head
def numpy_to_pydf(
data: np.ndarray[Any, Any],
schema: SchemaDefinition | None = None,
schema_overrides: SchemaDict | None = None,
orient: Orientation | None = None,
nan_to_null: bool = False,
) -> PyDataFrame:
"""Construct a PyDataFrame from a numpy ndarray."""
shape = data.shape
$ tail -n +1246 polars/utils/_construction.py | head
def iterable_to_pydf(
data: Iterable[Any],
schema: SchemaDefinition | None = None,
schema_overrides: SchemaDict | None = None,
orient: Orientation | None = None,
chunk_size: int | None = None,
infer_schema_length: int | None = N_INFER_DEFAULT,
) -> PyDataFrame:
"""Construct a PyDataFrame from an iterable/generator."""
original_schema = schema
The polars/utils/_construction.py:1050: error: Local variable "orient" has inferred type None; add an annotation can be "fixed" by not accessing orient in the else ValueError branch.
def numpy_to_pydf(
data: np.ndarray[Any, Any],
schema: SchemaDefinition | None = None,
schema_overrides: SchemaDict | None = None,
orient: Orientation | None = None,
nan_to_null: bool = False,
) -> PyDataFrame:
"""Construct a PyDataFrame from a numpy ndarray."""
shape = data.shape
# Unpack columns
if shape == (0,):
n_columns = 0
elif len(shape) == 1:
n_columns = 1
elif len(shape) == 2:
# default convention
# first axis is rows, second axis is columns
if orient is None and schema is None:
n_columns = shape[1]
orient = "row"
# Infer orientation if columns argument is given
elif orient is None and schema is not None:
if len(schema) == shape[0]:
orient = "col"
n_columns = shape[0]
else:
orient = "row"
n_columns = shape[1]
elif orient == "row":
n_columns = shape[1]
elif orient == "col":
n_columns = shape[0]
else:
raise ValueError(
# Only commenting out `{orient}`, seems to work.
# f"orient must be one of {{'col', 'row', None}}, got {orient} instead."
f"orient must be one of {{'col', 'row', None}}," # got {orient} instead."
)
else:
raise ValueError(
"Cannot create DataFrame from numpy array with more than two dimensions."
)
if schema is not None and len(schema) != n_columns:
raise ValueError("Dimensions of columns arg must match data dimensions.")
column_names, schema_overrides = _unpack_schema(
schema, schema_overrides=schema_overrides, n_expected=n_columns
)
# Convert data to series
if shape == (0,):
data_series = []
elif len(shape) == 1:
data_series = [
pli.Series(
name=column_names[0],
values=data,
dtype=schema_overrides.get(column_names[0]),
nan_to_null=nan_to_null,
)._s
]
else:
if orient == "row":
data_series = [
pli.Series(
name=column_names[i],
values=data[:, i],
dtype=schema_overrides.get(column_names[i]),
nan_to_null=nan_to_null,
)._s
for i in range(n_columns)
]
else:
data_series = [
pli.Series(
name=column_names[i],
values=data[i],
dtype=schema_overrides.get(column_names[i]),
nan_to_null=nan_to_null,
)._s
for i in range(n_columns)
]
data_series = _handle_columns_arg(data_series, columns=column_names)
return PyDataFrame(data_series)
Other things didn't seem to work:
❯ diff -u polars/utils/_construction.py polars/utils/_construction.py2
--- polars/utils/_construction.py 2023-03-27 15:17:50.072747854 +0200
+++ polars/utils/_construction.py2 2023-03-27 16:24:24.728991744 +0200
@@ -1076,14 +1076,16 @@
orient = "row"
n_columns = shape[1]
- elif orient == "row":
+ elif orient is not None and orient == "row":
n_columns = shape[1]
- elif orient == "col":
+ elif orient is not None and orient == "col":
n_columns = shape[0]
else:
+ #assert orient is not None
raise ValueError(
# f"orient must be one of {{'col', 'row', None}}, got {orient} instead."
- f"orient must be one of {{'col', 'row', None}}," # got {orient} instead."
+ f"orient must be one of {{'col', 'row', None}}, got {orient if orient is not None else 'None'} instead."
)
else:
raise ValueError(
@@ -1111,6 +1113,7 @@
)._s
]
else:
+ assert orient is not None
if orient == "row":
data_series = [
pli.Series(
For the other function, I have no clue how to "solve" polars/utils/_construction.py:1248: error: Local variable "schema" has inferred type None; add an annotation:
def iterable_to_pydf(
data: Iterable[Any],
schema: SchemaDefinition | None = None,
schema_overrides: SchemaDict | None = None,
orient: Orientation | None = None,
chunk_size: int | None = None,
infer_schema_length: int | None = N_INFER_DEFAULT,
) -> PyDataFrame:
"""Construct a PyDataFrame from an iterable/generator."""
original_schema = schema
column_names: list[str] = []
dtypes_by_idx: dict[int, PolarsDataType] = {}
if schema is not None:
column_names, schema_overrides = _unpack_schema(
schema, schema_overrides=schema_overrides
)
elif schema_overrides:
_, schema_overrides = _unpack_schema(schema, schema_overrides=schema_overrides)
if not isinstance(data, Generator):
data = iter(data)
if orient == "col":
if column_names and schema_overrides:
dtypes_by_idx = {
idx: schema_overrides.get(col, Unknown)
for idx, col in enumerate(column_names)
}
return pli.DataFrame(
{
(column_names[idx] if column_names else f"column_{idx}"): pli.Series(
coldata, dtype=dtypes_by_idx.get(idx)
)
for idx, coldata in enumerate(data)
}
)._df
def to_frame_chunk(values: list[Any], schema: SchemaDefinition | None) -> DataFrame:
return pli.DataFrame(
data=values,
schema=schema,
orient="row",
infer_schema_length=infer_schema_length,
)
n_chunks = 0
n_chunk_elems = 1_000_000
if chunk_size:
adaptive_chunk_size = chunk_size
elif column_names:
adaptive_chunk_size = n_chunk_elems // len(column_names)
else:
adaptive_chunk_size = None
df: DataFrame = None # type: ignore[assignment]
chunk_size = max(
(infer_schema_length or 0),
(adaptive_chunk_size or 1000),
)
while True:
values = list(islice(data, chunk_size))
if not values:
break
frame_chunk = to_frame_chunk(values, original_schema)
if df is None:
df = frame_chunk
if not original_schema:
original_schema = list(df.schema.items())
if chunk_size != adaptive_chunk_size:
chunk_size = adaptive_chunk_size = n_chunk_elems // len(df.columns)
else:
df.vstack(frame_chunk, in_place=True)
n_chunks += 1
if df is None:
df = to_frame_chunk([], original_schema)
return (df.rechunk() if n_chunks > 0 else df)._df
Expected Behavior
Actual Behavior
$ mypyc polars/utils/_construction.py
polars/utils/_construction.py:1050: error: Local variable "orient" has inferred type None; add an annotation
polars/utils/_construction.py:1248: error: Local variable "schema" has inferred type None; add an annotation
Your Environment
- Mypy version used:
1.1.1and1.3.0+dev.2e75cbaa8e5c0fb8aa3548d5c7c8ccfd00131057 - Mypy command-line flags:
- Mypy configuration options from
mypy.ini(and other config files): - Python version used: 3.8.10
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Riproduci il report con mypyc e mypy su polars/utils/_construction.py, concentrandoti sui punti di ingresso numpy_to_pydf e iterable_to_pydf. Traccia il modo in cui mypyc gestisce le variabili locali opzionali annotate e confronta i suoi diagnostici con quelli di mypy; il lavoro è completato quando gli errori di falso positivo segnalati non si verificano più e il controllo dei tipi valido rimane intatto.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- compilers, devtools
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 30/100