From 12840eb8ef37393a358b212eeb5c0992da8b18c2 Mon Sep 17 00:00:00 2001 From: Alexander Fischer Date: Wed, 1 Apr 2026 23:23:13 +0200 Subject: [PATCH] fix py13 import bug --- Cargo.lock | 2 +- Cargo.toml | 2 +- docs/changelog.qmd | 8 ++++- pyfixest/estimation/FixestMulti_.py | 2 ++ pyfixest/estimation/api/feglm.py | 2 ++ pyfixest/estimation/api/feols.py | 2 ++ pyfixest/estimation/api/fepois.py | 2 ++ pyfixest/estimation/api/quantreg.py | 2 ++ pyfixest/estimation/api/utils.py | 2 ++ pyfixest/estimation/models/feglm_.py | 2 ++ pyfixest/estimation/models/feols_.py | 4 ++- .../estimation/models/feols_compressed_.py | 2 ++ pyfixest/estimation/models/fepois_.py | 2 ++ .../estimation/post_estimation/prediction.py | 2 ++ pyfixest/estimation/quantreg/QuantregMulti.py | 2 ++ tests/test_import_annotations.py | 34 +++++++++++++++++++ 16 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 tests/test_import_annotations.py diff --git a/Cargo.lock b/Cargo.lock index da6fd2c87..58b9f5c0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1116,7 +1116,7 @@ dependencies = [ [[package]] name = "pyfixest_core" -version = "0.50.0" +version = "0.50.1" dependencies = [ "ndarray", "numpy", diff --git a/Cargo.toml b/Cargo.toml index 2dfbc638a..3b4a6b93d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyfixest_core" -version = "0.50.0" +version = "0.50.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/docs/changelog.qmd b/docs/changelog.qmd index 5fba25d2f..130382016 100644 --- a/docs/changelog.qmd +++ b/docs/changelog.qmd @@ -15,7 +15,13 @@ fit2 = pf.feols("Y ~ X1 + X2", data = df) fit3 = pf.feols("Y ~ X1 + X2 | f1", data = df) ``` -## PyFixest 0.50.0 (In Development) +## PyFixest 0.50.1 + +### Bug Fixes + +- Fixes an import-time failure on Python 3.13 in some environments where a `narwhals` typing alias was exposed as a string at runtime. This could cause imports of `feols()` / `feglm()` to fail before any model code ran. See [#1263](https://github.com/py-econometrics/pyfixest/issues/1263) for details. + +## PyFixest 0.50.0 ::: {.callout-tip} You can install the latest pre-release to try out the new features: diff --git a/pyfixest/estimation/FixestMulti_.py b/pyfixest/estimation/FixestMulti_.py index 1522ceea8..74587cb30 100644 --- a/pyfixest/estimation/FixestMulti_.py +++ b/pyfixest/estimation/FixestMulti_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools from collections.abc import Mapping from importlib import import_module diff --git a/pyfixest/estimation/api/feglm.py b/pyfixest/estimation/api/feglm.py index 25ce271ac..0ffff8c8f 100644 --- a/pyfixest/estimation/api/feglm.py +++ b/pyfixest/estimation/api/feglm.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections.abc import Mapping from typing import Any diff --git a/pyfixest/estimation/api/feols.py b/pyfixest/estimation/api/feols.py index 6e04d0a55..a603a2de4 100644 --- a/pyfixest/estimation/api/feols.py +++ b/pyfixest/estimation/api/feols.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections.abc import Mapping from typing import Any diff --git a/pyfixest/estimation/api/fepois.py b/pyfixest/estimation/api/fepois.py index f005376d5..cf87770e9 100644 --- a/pyfixest/estimation/api/fepois.py +++ b/pyfixest/estimation/api/fepois.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections.abc import Mapping from typing import Any diff --git a/pyfixest/estimation/api/quantreg.py b/pyfixest/estimation/api/quantreg.py index d20450c66..38dff9a03 100644 --- a/pyfixest/estimation/api/quantreg.py +++ b/pyfixest/estimation/api/quantreg.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections.abc import Mapping from typing import Any diff --git a/pyfixest/estimation/api/utils.py b/pyfixest/estimation/api/utils.py index dbe8b8c82..895da08b8 100644 --- a/pyfixest/estimation/api/utils.py +++ b/pyfixest/estimation/api/utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pandas as pd from pyfixest.utils.dev_utils import DataFrameType, _narwhals_to_pandas diff --git a/pyfixest/estimation/models/feglm_.py b/pyfixest/estimation/models/feglm_.py index 49d52c102..dcc067813 100644 --- a/pyfixest/estimation/models/feglm_.py +++ b/pyfixest/estimation/models/feglm_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC, abstractmethod from collections.abc import Mapping from typing import Any, Literal diff --git a/pyfixest/estimation/models/feols_.py b/pyfixest/estimation/models/feols_.py index 82532a7ed..cb1662cc3 100644 --- a/pyfixest/estimation/models/feols_.py +++ b/pyfixest/estimation/models/feols_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re import warnings from collections.abc import Callable, Mapping @@ -580,7 +582,7 @@ def vcov( vcov: str | dict[str, str], vcov_kwargs: dict[str, str | int] | None = None, data: DataFrameType | None = None, - ) -> "Feols": + ) -> Feols: """ Compute covariance matrices for an estimated regression model. diff --git a/pyfixest/estimation/models/feols_compressed_.py b/pyfixest/estimation/models/feols_compressed_.py index 845088ac8..a61aa9df6 100644 --- a/pyfixest/estimation/models/feols_compressed_.py +++ b/pyfixest/estimation/models/feols_compressed_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging from collections.abc import Mapping from dataclasses import dataclass diff --git a/pyfixest/estimation/models/fepois_.py b/pyfixest/estimation/models/fepois_.py index be6f1545d..3c22f9631 100644 --- a/pyfixest/estimation/models/fepois_.py +++ b/pyfixest/estimation/models/fepois_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re import warnings from collections.abc import Mapping diff --git a/pyfixest/estimation/post_estimation/prediction.py b/pyfixest/estimation/post_estimation/prediction.py index 39a9c34a0..415a0327c 100644 --- a/pyfixest/estimation/post_estimation/prediction.py +++ b/pyfixest/estimation/post_estimation/prediction.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re import warnings from collections.abc import Mapping diff --git a/pyfixest/estimation/quantreg/QuantregMulti.py b/pyfixest/estimation/quantreg/QuantregMulti.py index 35081c60e..0aedb6d45 100644 --- a/pyfixest/estimation/quantreg/QuantregMulti.py +++ b/pyfixest/estimation/quantreg/QuantregMulti.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import gc import inspect from collections.abc import Mapping diff --git a/tests/test_import_annotations.py b/tests/test_import_annotations.py new file mode 100644 index 000000000..3fb6724ca --- /dev/null +++ b/tests/test_import_annotations.py @@ -0,0 +1,34 @@ +import subprocess +import sys +import textwrap +from pathlib import Path + + +def test_stringified_dataframe_type_does_not_break_model_import(): + repo_root = Path(__file__).resolve().parents[1] + script = textwrap.dedent( + f""" + import importlib + import sys + + sys.path.insert(0, {str(repo_root)!r}) + + import pyfixest.utils.dev_utils as dev_utils + + # Reproduce the older narwhals behavior reported in issue #1263, where + # the imported typing alias behaved like a string at runtime. + dev_utils.DataFrameType = "IntoDataFrame" + + importlib.import_module("pyfixest.estimation.models.feglm_") + """ + ) + + result = subprocess.run( + [sys.executable, "-c", script], + capture_output=True, + text=True, + cwd=repo_root, + check=False, + ) + + assert result.returncode == 0, result.stderr or result.stdout