From 325883da4aafb814900b6cf798ba6b651b1c006f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 4 Oct 2025 15:32:55 +0100 Subject: [PATCH 1/7] Final changes --- .coveragerc | 40 ------------------------------------- ci/azure_template_posix.yml | 30 ++++++++++++++-------------- linearmodels/meson.build | 1 - pyproject.toml | 2 +- 4 files changed, 16 insertions(+), 57 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index d637030a4a..0000000000 --- a/.coveragerc +++ /dev/null @@ -1,40 +0,0 @@ -# .coveragerc to control coverage.py -[run] -source = linearmodels -branch = True -omit = - */results/* - */_version.py - */conftest.py - -[report] -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - except NotImplementedError - raise ImportError - - # Ignore failure messages - pytest.xfail - # Ignore ImportError protection - except ImportError - - # Ignore pass - pass - - # Don't complain if non-runnable code isn't run: - if 0: - if __name__ == .__main__.: - - # Ignore type checking code - if TYPE_CHECKING - - # Cython function declarations - cdef - -ignore_errors = True diff --git a/ci/azure_template_posix.yml b/ci/azure_template_posix.yml index 55ee539a23..17d7c1e4b9 100644 --- a/ci/azure_template_posix.yml +++ b/ci/azure_template_posix.yml @@ -23,7 +23,7 @@ jobs: PANDAS: 1.3.0 STATSMODELS: 0.13.1 XARRAY: 0.21.0 - FORMULAIC: 1.0.2 + FORMULAIC: 1.2.1 test.wheel: true python310_mid_sdist: python.version: '3.10' @@ -33,7 +33,7 @@ jobs: STATSMODELS: 0.13.1 XARRAY: 2022.6.0 XXHASH: true - FORMULAIC: 1.0.2 + FORMULAIC: 1.2.1 test.sdist: true python310_recent_wheel: python.version: '3.10' @@ -42,16 +42,15 @@ jobs: PANDAS: 2.0.0 STATSMODELS: 0.14.0 XARRAY: 2023.4.0 - FORMULAIC: 1.1.0 + FORMULAIC: 1.2.1 test.wheel: true python310_latest: python.version: '3.10' - FORMULAIC: 1.2.0 + FORMULAIC: 1.2.1 XXHASH: true PYARROW: true python310_no_cython: python.version: '3.10' - BUILD_FLAGS: '-Csetup-args=-Dno-binary=true' python311_latest: python.version: '3.11' XXHASH: true @@ -60,6 +59,11 @@ jobs: python.version: '3.12' XXHASH: true PYARROW: true + python312_latest_no_binary: + python.version: '3.12' + XXHASH: true + PYARROW: true + BUILD_FLAGS: '-Csetup-args=-Dno-binary=true' python313_latest: python.version: '3.13' XXHASH: true @@ -69,8 +73,8 @@ jobs: python.version: '3.12' XXHASH: true LM_TEST_COPY_ON_WRITE: 1 - python312_pre: - python.version: '3.12' + python313_pre: + python.version: '3.13' pip.pre: true maxParallel: 10 @@ -135,9 +139,7 @@ jobs: - script: | echo "Testing editable install" - if [[ ${COVERAGE} == "true" ]]; then - export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" - fi + export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests displayName: 'Run tests (editable)' @@ -145,9 +147,7 @@ jobs: - script: | echo "Testing pip-pre" - if [[ ${COVERAGE} == "true" ]]; then - export COVERAGE_OPTS="--cov-config .coveragerc --cov=linearmodels --cov-report xml:coverage.xml --cov-report term" - fi + export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests displayName: 'Run tests (pip pre)' @@ -163,11 +163,11 @@ jobs: - task: PublishCodeCoverageResults@2 inputs: summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' - condition: and(eq(variables['coverage'], 'true'), ne(variables['test.install'], 'true')) + condition: and(ne(variables['test.sdist'], 'true'), ne(variables['test.wheel'], 'true')) - script: | curl -Os https://uploader.codecov.io/latest/linux/codecov chmod +x codecov ./codecov -f coverage.xml -F adder -F subtractor displayName: 'Codecov upload' - condition: and(eq(variables['coverage'], 'true'), ne(variables['test.install'], 'true')) + condition: and(ne(variables['test.sdist'], 'true'), ne(variables['test.wheel'], 'true')) diff --git a/linearmodels/meson.build b/linearmodels/meson.build index cdbdc40576..b520c16e9e 100644 --- a/linearmodels/meson.build +++ b/linearmodels/meson.build @@ -29,7 +29,6 @@ inc_np = include_directories(incdir_numpy, is_system: true) # Copy the main __init__.py to the build dir. # Some submodules (linalg, special, optimize) add pxd files to this. # Needed to trick Cython, it won't do a relative import outside a package -_cython_tree = [fs.copyfile('__init__.py')] cython_args = [ '-Xcpow=True', '-Xboundscheck=False', diff --git a/pyproject.toml b/pyproject.toml index c0e2fb361c..c44994c88f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -311,7 +311,7 @@ include_trailing_comma=true use_parentheses=true [tool.coverage.run] -source = ["linearmodels"] +source = [ "linearmodels" ] branch = true plugins = ["Cython.Coverage"] omit = [ From e98654ea50f4477859ecc0d4fe56d1aac54a0fae Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 4 Oct 2025 21:53:28 +0100 Subject: [PATCH 2/7] Revert some --- ci/azure_template_posix.yml | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ci/azure_template_posix.yml b/ci/azure_template_posix.yml index 17d7c1e4b9..8599be69f1 100644 --- a/ci/azure_template_posix.yml +++ b/ci/azure_template_posix.yml @@ -23,7 +23,7 @@ jobs: PANDAS: 1.3.0 STATSMODELS: 0.13.1 XARRAY: 0.21.0 - FORMULAIC: 1.2.1 + FORMULAIC: 1.0.2 test.wheel: true python310_mid_sdist: python.version: '3.10' @@ -33,7 +33,7 @@ jobs: STATSMODELS: 0.13.1 XARRAY: 2022.6.0 XXHASH: true - FORMULAIC: 1.2.1 + FORMULAIC: 1.0.2 test.sdist: true python310_recent_wheel: python.version: '3.10' @@ -42,11 +42,11 @@ jobs: PANDAS: 2.0.0 STATSMODELS: 0.14.0 XARRAY: 2023.4.0 - FORMULAIC: 1.2.1 + FORMULAIC: 1.1.0 test.wheel: true python310_latest: python.version: '3.10' - FORMULAIC: 1.2.1 + FORMULAIC: 1.2.0 XXHASH: true PYARROW: true python310_no_cython: diff --git a/pyproject.toml b/pyproject.toml index c44994c88f..c0e2fb361c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -311,7 +311,7 @@ include_trailing_comma=true use_parentheses=true [tool.coverage.run] -source = [ "linearmodels" ] +source = ["linearmodels"] branch = true plugins = ["Cython.Coverage"] omit = [ From 080ff4ae386dae1921d1aac108c79d99d34070b3 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 4 Oct 2025 21:58:33 +0100 Subject: [PATCH 3/7] Fix CI --- ci/azure_template_posix.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ci/azure_template_posix.yml b/ci/azure_template_posix.yml index 8599be69f1..a3c99a500b 100644 --- a/ci/azure_template_posix.yml +++ b/ci/azure_template_posix.yml @@ -49,8 +49,6 @@ jobs: FORMULAIC: 1.2.0 XXHASH: true PYARROW: true - python310_no_cython: - python.version: '3.10' python311_latest: python.version: '3.11' XXHASH: true @@ -140,16 +138,16 @@ jobs: - script: | echo "Testing editable install" export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" - echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests - pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests + echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests + pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests displayName: 'Run tests (editable)' condition: and(and(ne(variables['test.wheel'], 'true'), ne(variables['test.sdist'], 'true')), ne(variables['pip.pre'], 'true')) - script: | echo "Testing pip-pre" export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" - echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests - pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests + echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests + pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests displayName: 'Run tests (pip pre)' condition: eq(variables['pip.pre'], 'true') continueOnError: true From f5db0d5141036665e2d3d9665779843c21238c75 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sat, 4 Oct 2025 22:39:23 +0100 Subject: [PATCH 4/7] Update azure_template_posix.yml --- ci/azure_template_posix.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci/azure_template_posix.yml b/ci/azure_template_posix.yml index a3c99a500b..d45f7fe15d 100644 --- a/ci/azure_template_posix.yml +++ b/ci/azure_template_posix.yml @@ -121,8 +121,8 @@ jobs: condition: eq(variables['test.wheel'], 'true') - script: | - echo python -m pip install --no-build-isolation -vv -e . ${FLAGS} - python -m pip install --no-build-isolation -vv -e . ${FLAGS} + echo python -m pip install --no-build-isolation -vv -e . ${BUILD_FLAGS} + python -m pip install --no-build-isolation -vv -e . ${BUILD_FLAGS} displayName: 'Install linearmodels (editable)' condition: and(ne(variables['test.wheel'], 'true'), ne(variables['test.sdist'], 'true')) @@ -139,7 +139,7 @@ jobs: echo "Testing editable install" export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests - pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests + pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests displayName: 'Run tests (editable)' condition: and(and(ne(variables['test.wheel'], 'true'), ne(variables['test.sdist'], 'true')), ne(variables['pip.pre'], 'true')) @@ -147,7 +147,7 @@ jobs: echo "Testing pip-pre" export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term" echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests - pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} ${BUILD_FLAGS} linearmodels/tests + pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests displayName: 'Run tests (pip pre)' condition: eq(variables['pip.pre'], 'true') continueOnError: true From b0e30bf12a9c252104b31d4aff473fe83e1c9602 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 5 Oct 2025 09:17:11 +0100 Subject: [PATCH 5/7] Restore CI changes --- ci/azure_template_posix.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci/azure_template_posix.yml b/ci/azure_template_posix.yml index d45f7fe15d..0e5bf7da24 100644 --- a/ci/azure_template_posix.yml +++ b/ci/azure_template_posix.yml @@ -23,7 +23,7 @@ jobs: PANDAS: 1.3.0 STATSMODELS: 0.13.1 XARRAY: 0.21.0 - FORMULAIC: 1.0.2 + FORMULAIC: 1.2.1 test.wheel: true python310_mid_sdist: python.version: '3.10' @@ -33,7 +33,7 @@ jobs: STATSMODELS: 0.13.1 XARRAY: 2022.6.0 XXHASH: true - FORMULAIC: 1.0.2 + FORMULAIC: 1.2.1 test.sdist: true python310_recent_wheel: python.version: '3.10' @@ -42,11 +42,11 @@ jobs: PANDAS: 2.0.0 STATSMODELS: 0.14.0 XARRAY: 2023.4.0 - FORMULAIC: 1.1.0 + FORMULAIC: 1.2.1 test.wheel: true python310_latest: python.version: '3.10' - FORMULAIC: 1.2.0 + FORMULAIC: 1.2.1 XXHASH: true PYARROW: true python311_latest: From 5497ecedd3190caa57e604b6a416df928f8209fd Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 5 Oct 2025 09:20:45 +0100 Subject: [PATCH 6/7] Blacklist wrapte 2.0.0rc3 --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 4b23ebff52..01274e83b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ statsmodels>=0.13.0 mypy_extensions>=0.4 pyhdfe>=0.1 formulaic>=1.0.2 +wrapt!=2.0.0rc3 \ No newline at end of file From dcc79364f9a7308eef271d9cda686fdff05e068f Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Sun, 5 Oct 2025 09:38:01 +0100 Subject: [PATCH 7/7] TST: add atol for tests with 0s --- linearmodels/tests/panel/test_data.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linearmodels/tests/panel/test_data.py b/linearmodels/tests/panel/test_data.py index 1a8b118abb..8c543c7bd5 100644 --- a/linearmodels/tests/panel/test_data.py +++ b/linearmodels/tests/panel/test_data.py @@ -656,7 +656,7 @@ def test_general_demean_oneway(mi_df): dm1 = y.demean("time") g = DataFrame(y.time_ids, index=y.index) dm2 = y.general_demean(g) - assert_allclose(dm1.values2d, dm2.values2d) + assert_allclose(dm1.values2d, dm2.values2d, atol=1e-10) g = DataFrame(np.random.randint(0, 10, g.shape), index=y.index) dm2 = y.general_demean(g) @@ -672,7 +672,7 @@ def test_general_demean_twoway(mi_df): g = DataFrame(y.entity_ids, index=y.index) g["column2"] = Series(y.time_ids.squeeze(), index=y.index) dm2 = y.general_demean(g) - assert_allclose(dm1.values2d, dm2.values2d) + assert_allclose(dm1.values2d, dm2.values2d, atol=1e-10) g = DataFrame(np.random.randint(0, 10, g.shape), index=y.index) dm2 = y.general_demean(g) @@ -692,16 +692,16 @@ def test_general_unit_weighted_demean_oneway(mi_df): weights = PanelData(g).copy() weights.dataframe.iloc[:, :] = 1 dm2 = y.general_demean(g, weights) - assert_allclose(dm1.values2d, dm2.values2d) + assert_allclose(dm1.values2d, dm2.values2d, atol=1e-10) dm3 = y.general_demean(g) - assert_allclose(dm3.values2d, dm2.values2d) + assert_allclose(dm3.values2d, dm2.values2d, atol=1e-10) dm1 = y.demean("time") g = PanelData(DataFrame(y.time_ids, index=y.index)) dm2 = y.general_demean(g, weights) - assert_allclose(dm1.values2d, dm2.values2d) + assert_allclose(dm1.values2d, dm2.values2d, atol=1e-10) dm3 = y.general_demean(g) - assert_allclose(dm3.values2d, dm2.values2d) + assert_allclose(dm3.values2d, dm2.values2d, atol=1e-10) g = PanelData(DataFrame(np.random.randint(0, 10, g.dataframe.shape), index=y.index)) dm2 = y.general_demean(g, weights) @@ -709,7 +709,7 @@ def test_general_unit_weighted_demean_oneway(mi_df): g = Categorical(g.dataframe.iloc[:, 0]) d = get_dummies(g) dm1 = y.values2d - d @ lstsq(d, y.values2d, rcond=None)[0] - assert_allclose(dm1, dm2.values2d) + assert_allclose(dm1, dm2.values2d, atol=1e-10) assert_allclose(dm3.values2d, dm2.values2d, atol=1e-10) @@ -723,12 +723,12 @@ def test_general_weighted_demean_oneway(mi_df): dm1 = y.demean("entity", weights=w) g = PanelData(DataFrame(y.entity_ids, index=y.index)) dm2 = y.general_demean(g, w) - assert_allclose(dm1.values2d, dm2.values2d) + assert_allclose(dm1.values2d, dm2.values2d, atol=1e-10) dm1 = y.demean("time", weights=w) g = PanelData(DataFrame(y.time_ids, index=y.index)) dm2 = y.general_demean(g, w) - assert_allclose(dm1.values2d, dm2.values2d) + assert_allclose(dm1.values2d, dm2.values2d, atol=1e-10) g = PanelData(DataFrame(np.random.randint(0, 10, g.dataframe.shape), index=y.index)) dm2 = y.general_demean(g, w)