Skip to content

Commit 3dd92a3

Browse files
authored
Merge pull request #666 from bashtage/use-meson
BLD: Add meson
2 parents 764475a + ecb8e7d commit 3dd92a3

File tree

16 files changed

+631
-185
lines changed

16 files changed

+631
-185
lines changed

.flake8

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[flake8]
2+
# Leave at 99 for now
3+
max-line-length = 99
4+
ignore = E203,W503,BLK100
5+
per-file-ignores =
6+
linearmodels/panel/data.py: E704
7+
linearmodels/shared/utility.py: F811, E704
8+
linearmodels/panel/utility.py: F811

ci/azure_template_posix.yml

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ parameters:
1111

1212
jobs:
1313

14-
- job: ${{ parameters.name }}Test
14+
- job: ${{ parameters.name }}_Test
1515
pool:
1616
vmImage: ${{ parameters.vmImage }}
1717
strategy:
1818
matrix:
19-
python310_minimums:
19+
python310_minimums_wheel:
2020
python.version: '3.10'
2121
NUMPY: 1.22.3
2222
SCIPY: 1.8.0
2323
PANDAS: 1.3.0
2424
STATSMODELS: 0.13.1
2525
XARRAY: 0.21.0
2626
FORMULAIC: 1.0.2
27-
test.install: true
28-
python310_mid:
27+
test.wheel: true
28+
python310_mid_sdist:
2929
python.version: '3.10'
3030
NUMPY: 1.23.0
3131
SCIPY: 1.9.0
@@ -34,24 +34,24 @@ jobs:
3434
XARRAY: 2022.6.0
3535
XXHASH: true
3636
FORMULAIC: 1.0.2
37-
test.install: true
38-
python310_recent:
37+
test.sdist: true
38+
python310_recent_wheel:
3939
python.version: '3.10'
4040
NUMPY: 1.24.0
4141
SCIPY: 1.12.0
4242
PANDAS: 2.0.0
4343
STATSMODELS: 0.14.0
4444
XARRAY: 2023.4.0
4545
FORMULAIC: 1.1.0
46-
test.install: true
46+
test.wheel: true
4747
python310_latest:
4848
python.version: '3.10'
4949
FORMULAIC: 1.2.0
5050
XXHASH: true
5151
PYARROW: true
5252
python310_no_cython:
5353
python.version: '3.10'
54-
LM_NO_BINARY: 1
54+
BUILD_FLAGS: '-Csetup-args=-Dno-binary=true'
5555
python311_latest:
5656
python.version: '3.11'
5757
XXHASH: true
@@ -64,6 +64,7 @@ jobs:
6464
python.version: '3.13'
6565
XXHASH: true
6666
PYARROW: true
67+
BUILD_FLAGS: '-Csetup-args=-Dcython-coverage=true'
6768
python313_copy_on_write:
6869
python.version: '3.12'
6970
XXHASH: true
@@ -81,7 +82,7 @@ jobs:
8182
displayName: 'Use Python $(python.version)'
8283

8384
- script: |
84-
python -m pip install --upgrade pip setuptools>=61 wheel
85+
python -m pip install --upgrade pip wheel build
8586
python -m pip install -r requirements.txt
8687
python -m pip install -r requirements-test.txt
8788
python -m pip install -r requirements-dev.txt
@@ -102,18 +103,26 @@ jobs:
102103
displayName: 'Check style and formatting'
103104
104105
- script: |
105-
echo "Installing to site packages"
106-
python -m pip wheel . --wheel-dir ./dist/ --no-build-isolation
106+
echo "Installing to site packages (sdist)"
107+
python -m build --sdist . -v
108+
SDIST=$(ls -t ./dist/linearmodels-*.tar.gz | head -1)
109+
pip install ${SDIST} -v
110+
displayName: 'Install linearmodels (site-packages)'
111+
condition: eq(variables['test.sdist'], 'true')
112+
113+
- script: |
114+
echo "Installing to site packages (wheel)"
115+
python -m pip wheel . --wheel-dir ./dist/
107116
WHL=$(ls -t ./dist/linearmodels-*.whl | head -1)
108-
pip install ${WHL}
117+
pip install ${WHL} -v
109118
displayName: 'Install linearmodels (site-packages)'
110-
condition: eq(variables['test.install'], 'true')
119+
condition: eq(variables['test.wheel'], 'true')
111120
112121
- script: |
113-
echo python -m pip install -e . -v --no-build-isolation
114-
python -m pip install -e . -v --no-build-isolation
122+
echo python -m pip install --no-build-isolation -vv -e . ${FLAGS}
123+
python -m pip install --no-build-isolation -vv -e . ${FLAGS}
115124
displayName: 'Install linearmodels (editable)'
116-
condition: ne(variables['test.install'], 'true')
125+
condition: and(ne(variables['test.wheel'], 'true'), ne(variables['test.sdist'], 'true'))
117126
118127
- script: |
119128
echo "Testing site packages"
@@ -122,17 +131,17 @@ jobs:
122131
python -c "import linearmodels; linearmodels.test(['-n', 'auto', '--junitxml=../junit/test-results.xml'])"
123132
popd
124133
displayName: 'Run tests (site-packages)'
125-
condition: and(eq(variables['test.install'], 'true'), ne(variables['pip.pre'], 'true'))
134+
condition: or(eq(variables['test.wheel'], 'true'), eq(variables['test.sdist'], 'true'))
126135
127136
- script: |
128137
echo "Testing editable install"
129138
if [[ ${COVERAGE} == "true" ]]; then
130-
export COVERAGE_OPTS="--cov-config .coveragerc --cov=linearmodels --cov-report xml:coverage.xml --cov-report term"
139+
export COVERAGE_OPTS="--cov=linearmodels --cov-report xml:coverage.xml --cov-report term"
131140
fi
132141
echo pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests
133142
pytest -m "${PYTEST_PATTERN}" --junitxml=junit/test-results.xml -n auto --durations=25 ${COVERAGE_OPTS} linearmodels/tests
134143
displayName: 'Run tests (editable)'
135-
condition: and(ne(variables['test.install'], 'true'), ne(variables['pip.pre'], 'true'))
144+
condition: and(and(ne(variables['test.wheel'], 'true'), ne(variables['test.sdist'], 'true')), ne(variables['pip.pre'], 'true'))
136145
137146
- script: |
138147
echo "Testing pip-pre"

examples/system_examples.ipynb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
"\n",
185185
"cov = res.sigma\n",
186186
"std = np.sqrt(np.diag(res.sigma)[:, None])\n",
187-
"regions = [k for k in mod_data.keys()]\n",
187+
"regions = list(mod_data.keys())\n",
188188
"corr = pd.DataFrame(cov / (std @ std.T), columns=regions, index=regions)\n",
189189
"\n",
190190
"sns.heatmap(corr, vmax=0.8, square=True)\n",
@@ -257,9 +257,7 @@
257257
"outputs": [],
258258
"source": [
259259
"# TODO: Implement method to compare across equations\n",
260-
"params = []\n",
261-
"for label in res.equation_labels:\n",
262-
" params.append(res.equations[label].params)\n",
260+
"params = [res.equations[label].params for label in res.equation_labels]\n",
263261
"params = pd.concat(params, axis=1)\n",
264262
"params.columns = res.equation_labels\n",
265263
"params.T.style.format(\"{:0.3f}\")"
@@ -732,7 +730,6 @@
732730
"outputs": [],
733731
"source": [
734732
"import statsmodels.api as sm\n",
735-
"\n",
736733
"from linearmodels.datasets import french\n",
737734
"\n",
738735
"data = french.load()\n",
@@ -779,7 +776,7 @@
779776
"name": "python",
780777
"nbconvert_exporter": "python",
781778
"pygments_lexer": "ipython3",
782-
"version": "3.12.9"
779+
"version": "3.13.7"
783780
},
784781
"pycharm": {
785782
"stem_cell": {

examples/system_three-stage-ls.ipynb

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
"metadata": {},
136136
"outputs": [],
137137
"source": [
138-
"equations = dict(hours=hours, lwage=lwage)\n",
138+
"equations = {\"hours\": hours, \"lwage\": lwage}\n",
139139
"system_2sls = IV3SLS.from_formula(equations, data)\n",
140140
"system_2sls_res = system_2sls.fit(method=\"ols\", cov_type=\"unadjusted\")\n",
141141
"print(system_2sls_res)"
@@ -154,7 +154,6 @@
154154
"metadata": {},
155155
"outputs": [],
156156
"source": [
157-
"equations = dict(hours=hours, lwage=lwage)\n",
158157
"system_3sls = IV3SLS.from_formula(equations, data)\n",
159158
"system_3sls_res = system_3sls.fit(method=\"gls\", cov_type=\"unadjusted\")\n",
160159
"print(system_3sls_res)"
@@ -196,7 +195,7 @@
196195
" \"instruments\": data[[\"age\", \"kidslt6\", \"nwifeinc\"]],\n",
197196
"}\n",
198197
"\n",
199-
"equations = dict(hours=hours, lwage=lwage)\n",
198+
"equations = {\"hours\": hours, \"lwage\": lwage}\n",
200199
"system_3sls = IV3SLS(equations)\n",
201200
"system_3sls_res = system_3sls.fit(cov_type=\"unadjusted\")\n",
202201
"print(system_3sls_res)"
@@ -223,10 +222,10 @@
223222
"metadata": {},
224223
"outputs": [],
225224
"source": [
226-
"equations = dict(\n",
227-
" hours=\"hours ~ educ + age + kidslt6 + nwifeinc + [lwage ~ exper + expersq]\",\n",
228-
" lwage=\"lwage ~ educ + exper + expersq + [hours ~ age + kidslt6 + nwifeinc]\",\n",
229-
")\n",
225+
"equations = {\n",
226+
" \"hours\": \"hours ~ educ + age + kidslt6 + nwifeinc + [lwage ~ exper + expersq]\",\n",
227+
" \"lwage\": \"lwage ~ educ + exper + expersq + [hours ~ age + kidslt6 + nwifeinc]\",\n",
228+
"}\n",
230229
"system_gmm = IVSystemGMM.from_formula(equations, data, weight_type=\"unadjusted\")\n",
231230
"system_gmm_res = system_gmm.fit(cov_type=\"unadjusted\")\n",
232231
"print(system_gmm_res)"
@@ -295,7 +294,7 @@
295294
"in_sample = df.iloc[:-10000]\n",
296295
"oos = df.iloc[-10000:]\n",
297296
"mod = IV3SLS.from_formula(\n",
298-
" dict(y1=\"y1 ~ x1 + [y2 ~ x2]\", y2=\"y2 ~ x2 + [y1 ~ x1]\"), data=df\n",
297+
" {\"y1\": \"y1 ~ x1 + [y2 ~ x2]\", \"y2\": \"y2 ~ x2 + [y1 ~ x1]\"}, data=df\n",
299298
")\n",
300299
"res = mod.fit()\n",
301300
"print(res)"
@@ -353,7 +352,7 @@
353352
"name": "python",
354353
"nbconvert_exporter": "python",
355354
"pygments_lexer": "ipython3",
356-
"version": "3.12.9"
355+
"version": "3.13.7"
357356
},
358357
"pycharm": {
359358
"stem_cell": {

linearmodels/_build/__init__.py

Whitespace-only changes.

linearmodels/_build/git_version.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
from __future__ import annotations
3+
4+
import os
5+
import setuptools_scm
6+
from packaging.version import Version
7+
from pathlib import Path
8+
9+
ROOT = Path(__file__).parent.parent.parent.absolute()
10+
11+
12+
def get_version() -> tuple[str, tuple[int | str, ...]]:
13+
_version = setuptools_scm.get_version(root=ROOT)
14+
parsed_version = Version(_version)
15+
version_fields: tuple[int | str, ...] = parsed_version.release
16+
if parsed_version.epoch:
17+
version_fields = (f"{parsed_version.epoch}!", *version_fields)
18+
if parsed_version.pre is not None:
19+
version_fields += (f"{parsed_version.pre[0]}{parsed_version.pre[1]}",)
20+
21+
if parsed_version.post is not None:
22+
version_fields += (f"post{parsed_version.post}",)
23+
24+
if parsed_version.dev is not None:
25+
version_fields += (f"dev{parsed_version.dev}",)
26+
27+
if parsed_version.local is not None:
28+
version_fields += (parsed_version.local,)
29+
30+
return _version, version_fields
31+
32+
33+
def write_version_file(
34+
filename: str, version: str, version_fields: tuple[int | str, ...]
35+
) -> None:
36+
template = f"""# file generated by setuptools-scm
37+
# don't change, don't track in version control
38+
39+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
40+
41+
TYPE_CHECKING = False
42+
if TYPE_CHECKING:
43+
from typing import Tuple
44+
from typing import Union
45+
46+
VERSION_TUPLE = Tuple[Union[int, str], ...]
47+
else:
48+
VERSION_TUPLE = object
49+
50+
version: str
51+
__version__: str
52+
__version_tuple__: VERSION_TUPLE
53+
version_tuple: VERSION_TUPLE
54+
55+
__version__ = version = '{version}'
56+
__version_tuple__ = version_tuple = {version_fields}
57+
"""
58+
59+
with open(filename, "w") as f:
60+
f.write(template)
61+
62+
63+
if __name__ == "__main__":
64+
import argparse
65+
66+
parser = argparse.ArgumentParser()
67+
parser.add_argument("--write", help="Save version to this file")
68+
parser.add_argument(
69+
"--meson-dist",
70+
help="Output path is relative to MESON_DIST_ROOT",
71+
action="store_true",
72+
)
73+
args = parser.parse_args()
74+
75+
version, version_tuple = get_version()
76+
77+
if args.write:
78+
outfile = args.write
79+
if args.meson_dist:
80+
outfile = os.path.join(os.environ.get("MESON_DIST_ROOT", ""), outfile)
81+
82+
# Print human readable output path
83+
relpath = os.path.relpath(outfile)
84+
if relpath.startswith("."):
85+
relpath = outfile
86+
write_version_file(relpath, version, version_tuple)
87+
else:
88+
print(version)

0 commit comments

Comments
 (0)