Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
full_name = os.path.split(file_to_copy)[-1]
folder, file_name = full_name.split("_")
if not file_name.endswith("ipynb"):
file_name = "_".join((folder, file_name))
file_name = f"{folder}_{file_name}"
out_dir = os.path.join(folder, "examples")
if not os.path.exists(out_dir):
os.makedirs(out_dir, exist_ok=True)
Expand Down
8 changes: 4 additions & 4 deletions linearmodels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
from .system import IV3SLS, SUR, IVSystemGMM

OLS = _OLS
WARN_ON_MISSING = os.environ.get("LINEARMODELS_WARN_ON_MISSING", "1")
WARN_ON_MISSING = False if WARN_ON_MISSING in ("", "0", "false", "False") else True
DROP_MISSING = os.environ.get("LINEARMODELS_DROP_MISSING", "1")
DROP_MISSING = False if DROP_MISSING in ("", "0", "false", "False") else True
_WARN_ON_MISSING = os.environ.get("LINEARMODELS_WARN_ON_MISSING", "1")
WARN_ON_MISSING = False if _WARN_ON_MISSING in ("", "0", "false", "False") else True
_DROP_MISSING = os.environ.get("LINEARMODELS_DROP_MISSING", "1")
DROP_MISSING = False if _DROP_MISSING in ("", "0", "false", "False") else True

__all__ = [
"DROP_MISSING",
Expand Down
6 changes: 3 additions & 3 deletions linearmodels/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
logger.critical("Copy on Write testing enabled")


def pytest_configure(config):
def pytest_configure(config: pytest.Config) -> None:
# Minimal config to simplify running tests from lm.test()
config.addinivalue_line("markers", "example: mark a test as an example")
config.addinivalue_line("markers", "slow: mark a test as slow")
Expand All @@ -32,15 +32,15 @@ def pytest_configure(config):
)


def pytest_addoption(parser):
def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption("--skip-slow", action="store_true", help="skip slow tests")
parser.addoption("--only-slow", action="store_true", help="run only slow tests")
parser.addoption("--skip-smoke", action="store_true", help="skip smoke tests")
parser.addoption("--only-smoke", action="store_true", help="run only smoke tests")
parser.addoption("--skip-examples", action="store_true", help="skip examples tests")


def pytest_runtest_setup(item):
def pytest_runtest_setup(item: pytest.Item) -> None:
if "slow" in item.keywords and item.config.getoption("--skip-slow"):
pytest.skip("skipping due to --skip-slow")

Expand Down
20 changes: 11 additions & 9 deletions linearmodels/iv/absorbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def __init__(self) -> None:
self._hasher = hashlib.sha256()
self._use_xxh64 = False

def reset(self):
def reset(self) -> None:
if self._use_xxh64:
assert isinstance(self._hasher, xxh64)
self._hasher.reset()
Expand Down Expand Up @@ -108,7 +108,7 @@ def lsmr_annihilate(
use_cache: bool = True,
x_hash: Hashable | None = None,
**lsmr_options: (
bool | float | str | linearmodels.typing.data.ArrayLike | None | dict[str, Any]
bool | float | str | linearmodels.typing.data.ArrayLike | dict[str, Any] | None
),
) -> linearmodels.typing.data.Float64Array:
r"""
Expand Down Expand Up @@ -149,7 +149,7 @@ def lsmr_annihilate(
regressor_hash = x_hash if x_hash is not None else ""
default_opts: dict[
str,
bool | float | str | linearmodels.typing.data.ArrayLike | None | dict[str, Any],
bool | float | str | linearmodels.typing.data.ArrayLike | dict[str, Any] | None,
] = {"atol": 1e-8, "btol": 1e-8, "show": False}
assert lsmr_options is not None
default_opts.update(lsmr_options)
Expand Down Expand Up @@ -865,16 +865,17 @@ def _prepare_interactions(self) -> None:
def _first_time_fit(
self,
use_cache: bool,
absorb_options: None | (
absorb_options: (
dict[
str,
bool
| float
| str
| linearmodels.typing.data.ArrayLike
| None
| dict[str, Any],
| dict[str, Any]
| None,
]
| None
),
method: str,
) -> None:
Expand Down Expand Up @@ -988,16 +989,17 @@ def fit(
cov_type: str = "robust",
debiased: bool = False,
method: str = "auto",
absorb_options: None | (
absorb_options: (
dict[
str,
bool
| float
| str
| linearmodels.typing.data.ArrayLike
| None
| dict[str, Any],
| dict[str, Any]
| None,
]
| None
) = None,
use_cache: bool = True,
lsmr_options: dict[str, float | bool] | None = None,
Expand Down
2 changes: 1 addition & 1 deletion linearmodels/iv/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ def predict(
return out_df

@property
def kappa(self) -> float:
def kappa(self) -> float | None:
"""k-class estimator value"""
return self._kappa

Expand Down
4 changes: 2 additions & 2 deletions linearmodels/panel/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def entities(self) -> list[linearmodels.typing.Label]:
return list(index.levels[0][index.codes[0]].unique())

@property
def entity_ids(self) -> linearmodels.typing.data.IntArray:
def entity_ids(self) -> linearmodels.typing.data.AnyIntArray:
"""
Get array containing entity group membership information

Expand All @@ -371,7 +371,7 @@ def entity_ids(self) -> linearmodels.typing.data.IntArray:
return np.asarray(index.codes[0])[:, None]

@property
def time_ids(self) -> linearmodels.typing.data.IntArray:
def time_ids(self) -> linearmodels.typing.data.AnyIntArray:
"""
Get array containing time membership information

Expand Down
2 changes: 2 additions & 0 deletions linearmodels/shared/hypotheses.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from collections.abc import Mapping
from typing import Any

from formulaic.utils.constraints import LinearConstraints
import numpy as np
Expand Down Expand Up @@ -46,6 +47,7 @@ def __init__(
self.df = df
self.df_denom = df_denom
self._name = name
self.dist: Any
if df_denom is None:
self.dist = chi2(df)
self.dist_name = f"chi2({df})"
Expand Down
7 changes: 5 additions & 2 deletions linearmodels/system/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -909,8 +909,11 @@ def _common_indiv_results(
constant: bool,
total_ss: float,
*,
weight_est: None | (
HomoskedasticWeightMatrix | HeteroskedasticWeightMatrix | KernelWeightMatrix
weight_est: (
HomoskedasticWeightMatrix
| HeteroskedasticWeightMatrix
| KernelWeightMatrix
| None
) = None,
) -> AttrDict:
loc = 0
Expand Down
14 changes: 8 additions & 6 deletions linearmodels/tests/asset_pricing/test_linear_factor_gmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,21 @@ def test_linear_model_gmm_smoke_risk_free(data):
mod = LinearFactorModelGMM(data.portfolios, data.factors, risk_free=True)
res = mod.fit(cov_type="robust", disp=10)
get_all(res)
str(res._cov_est)
res._cov_est.__repr__()
str(res._cov_est.config)
# Smoke tests
assert isinstance(str(res._cov_est), str)
assert isinstance(res._cov_est.__repr__(), str)
assert isinstance(str(res._cov_est.config), str)


@pytest.mark.smoke
def test_linear_model_gmm_kernel_smoke(data):
mod = LinearFactorModelGMM(data.portfolios, data.factors)
res = mod.fit(cov_type="kernel", disp=10)
get_all(res)
str(res._cov_est)
res._cov_est.__repr__()
str(res._cov_est.config)
# Smoke tests
assert isinstance(str(res._cov_est), str)
assert isinstance(res._cov_est.__repr__(), str)
assert isinstance(str(res._cov_est.config), str)


@pytest.mark.smoke
Expand Down
8 changes: 4 additions & 4 deletions linearmodels/tests/iv/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,10 @@ def test_first_stage_summary(data):

def test_gmm_str(data):
mod = IVGMM(data.dep, data.exog, data.endog, data.instr)
str(mod.fit(cov_type="unadjusted"))
str(mod.fit(cov_type="robust"))
str(mod.fit(cov_type="clustered", clusters=data.clusters))
str(mod.fit(cov_type="kernel"))
assert isinstance(str(mod.fit(cov_type="unadjusted")), str)
assert isinstance(str(mod.fit(cov_type="robust")), str)
assert isinstance(str(mod.fit(cov_type="clustered", clusters=data.clusters)), str)
assert isinstance(str(mod.fit(cov_type="kernel")), str)


def test_gmm_cue_optimization_options(small_data):
Expand Down
2 changes: 1 addition & 1 deletion linearmodels/tests/iv/test_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def result_checker(res):
_attr()
else:
assert isinstance(_attr, object)
str(_attr)
assert isinstance(str(_attr), str)


def test_results(data, model):
Expand Down
6 changes: 2 additions & 4 deletions linearmodels/tests/system/results/execute-stata-3sls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@
STATA_PATH = os.path.join("C:\\", "Program Files (x86)", "Stata15", "StataMP-64.exe")
OUTFILE = os.path.join(os.getcwd(), "stata-3sls-results.txt")

header = [
r'use "C:\git\linearmodels\linearmodels\tests\system\results\simulated-3sls.dta",'
r" clear"
]
header = r'use "C:\git\linearmodels\linearmodels\tests\system\results\simulated-3sls.dta", clear'


all_stats = (
"estout using {outfile}, cells(b(fmt(%13.12g)) t(fmt(%13.12g)) "
Expand Down
5 changes: 1 addition & 4 deletions linearmodels/tests/system/results/execute-stata.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@
STATA_PATH = os.path.join("C:\\", "Program Files (x86)", "Stata13", "StataMP-64.exe")
OUTFILE = os.path.join(os.getcwd(), "stata-sur-results.txt")

header = [
r'use "C:\git\linearmodels\linearmodels\tests\system\results\simulated-sur.dta"'
", clear"
]
header = r'use "C:\git\linearmodels\linearmodels\tests\system\results\simulated-sur.dta", clear'

all_stats = (
"estout using {outfile}, cells(b(fmt(%13.12g)) "
Expand Down
4 changes: 4 additions & 0 deletions linearmodels/typing/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import pandas as pd

base_data_types = [np.ndarray, pd.DataFrame, pd.Series]

try:
import xarray as xr

ArrayLike = Union[np.ndarray, xr.DataArray, pd.DataFrame, pd.Series]

except ImportError:

# Always needed to allow optional xarray
ArrayLike = Union[np.ndarray, pd.DataFrame, pd.Series]

Expand All @@ -20,13 +22,15 @@
Int64Array = np.ndarray[tuple[int, ...], np.dtype[np.int64]] # pragma: no cover
Int32Array = np.ndarray[tuple[int, ...], np.dtype[np.int32]] # pragma: no cover
IntArray = np.ndarray[tuple[int, ...], np.dtype[np.int_]] # pragma: no cover
AnyIntArray = np.ndarray[tuple[int, ...], np.dtype[np.integer]] # pragma: no cover
BoolArray = np.ndarray[tuple[int, ...], np.dtype[np.bool_]] # pragma: no cover
AnyArray = np.ndarray[tuple[int, ...], Any] # pragma: no cover
Uint32Array = np.ndarray[tuple[int, ...], np.dtype[np.uint32]] # pragma: no cover
FloatArray1D = np.ndarray[tuple[int], np.dtype[np.float64]]
FloatArray2D = np.ndarray[tuple[int, int], np.dtype[np.float64]]
__all__ = [
"AnyArray",
"AnyIntArray",
"ArrayLike",
"BoolArray",
"Float64Array",
Expand Down
11 changes: 6 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ dev = [
"pytest-xdist",
"pytest-cov",
# formatting
"black[jupyter]~=25.9.0",
"isort~=6.0",
"black[jupyter]~=26.5.0",
"isort~=9.0",
"colorama",
"flake8",
"flake8-bugbear",
"mypy>=1.3",
"ruff>=0.8.6",
"ruff>=0.16.0",
"pyupgrade>=3.4.0",
"jupyterlab-code-formatter",
"jupyterlab>=4.4.8", # not directly required, pinned by Snyk to avoid a vulnerability
Expand All @@ -153,7 +153,7 @@ setup = ['--vsenv']
version_file = "arch/_version.py"

[tool.black]
target-version = ['py310', 'py311', 'py312', 'py313']
target-version = ['py310', 'py311', 'py312', 'py313', 'py314']
exclude = '''
(
\.egg
Expand Down Expand Up @@ -256,6 +256,8 @@ ignore = [
"PLR0915", # 21
# Magic number
"PLR2004",
# Too many positional arguments
"PLR0917",
# Like to suggest use [a, *b] instead of [a] + b
"RUF005",
]
Expand Down Expand Up @@ -376,7 +378,6 @@ omit = [
directory = "coverage_html_report"

[tool.mypy]
plugins="numpy.typing.mypy_plugin"
exclude = [
"tests",
]
Expand Down
6 changes: 3 additions & 3 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ matplotlib

# Linting
mypy>=1.3
black[jupyter]~=25.9.0
isort>=5.12
ruff>=0.8.6
black[jupyter]~=26.5.0
isort>=9.0
ruff>=0.16.0
flake8
flake8-bugbear
pandas-stubs
Expand Down
5 changes: 3 additions & 2 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
black[jupyter]~=25.9.0
black[jupyter]~=26.5.0
coverage
flake8
isort
ruff
colorama
matplotlib
pytest>=8.4.1,<9
pytest>=9,<10
pytest-xdist
pytest-cov
pytest-randomly
Expand Down
Loading