Skip to content

Commit 9b95e63

Browse files
Merge branch 'master' into oetc-support
2 parents d6ddfa0 + 7c68c9e commit 9b95e63

File tree

8 files changed

+112
-111
lines changed

8 files changed

+112
-111
lines changed
File renamed without changes.

.github/workflows/test-models.yml

Lines changed: 82 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ name: Test models
33
on:
44
push:
55
branches:
6-
- master
6+
- master
77
pull_request:
88
branches:
9-
- master
9+
- master
1010
schedule:
11-
- cron: "0 5 * * *"
11+
- cron: "0 5 * * *"
1212

1313
# Cancel any in-progress runs when a new run is triggered
1414
concurrency:
@@ -23,89 +23,89 @@ jobs:
2323
fail-fast: false
2424
matrix:
2525
version:
26-
- master
26+
- master
2727
# - latest # Activate when v0.14.0 is released
2828

2929
defaults:
3030
run:
3131
shell: bash -l {0}
3232

3333
steps:
34-
- uses: actions/checkout@v4
35-
with:
36-
repository: PyPSA/pypsa-eur
37-
ref: master
38-
39-
- name: Check out latest release
40-
if: matrix.version == 'latest'
41-
run: |
42-
git fetch --tags
43-
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
44-
git checkout $latest_tag
45-
46-
# Only run check if package is not pinned
47-
- name: Check if inhouse package is pinned
48-
run: |
49-
grep_line=$(grep -- '- pypsa' envs/environment.yaml)
50-
if [[ $grep_line == *"<"* || $grep_line == *"=="* ]]; then
51-
echo "pinned=true" >> $GITHUB_ENV
52-
else
53-
echo "pinned=false" >> $GITHUB_ENV
54-
fi
55-
56-
- name: Setup secrets & cache dates
57-
if: env.pinned == 'false'
58-
run: |
59-
echo -ne "url: ${CDSAPI_URL}\nkey: ${CDSAPI_TOKEN}\n" > ~/.cdsapirc
60-
echo "week=$(date +'%Y%U')" >> $GITHUB_ENV # data and cutouts
61-
62-
- uses: actions/cache@v4
63-
if: env.pinned == 'false'
64-
with:
65-
path: |
66-
data
67-
cutouts
68-
key: data-cutouts-${{ env.week }}
69-
70-
- uses: conda-incubator/setup-miniconda@v3
71-
if: env.pinned == 'false'
72-
with:
73-
activate-environment: pypsa-eur
74-
75-
- name: Cache Conda env
76-
if: env.pinned == 'false'
77-
uses: actions/cache@v4
78-
with:
79-
path: ${{ env.CONDA }}/envs
80-
key: conda-pypsa-eur-${{ env.week }}-${{ hashFiles('envs/linux-pinned.yaml') }}
81-
id: cache-env
82-
83-
- name: Update environment
84-
if: env.pinned == 'false' && steps.cache-env.outputs.cache-hit != 'true'
85-
run: conda env update -n pypsa-eur -f envs/linux-pinned.yaml
86-
87-
- name: Install package from ref
88-
if: env.pinned == 'false'
89-
run: |
90-
python -m pip install git+https://github.com/${{ github.repository }}@${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
91-
92-
- name: Run snakemake test workflows
93-
if: env.pinned == 'false'
94-
run: |
95-
make test
96-
97-
- name: Run unit tests
98-
if: env.pinned == 'false'
99-
run: |
100-
make unit-test
101-
102-
- name: Upload artifacts
103-
if: env.pinned == 'false'
104-
uses: actions/upload-artifact@v4
105-
with:
106-
name: results-pypsa-eur-${{ matrix.version }}
107-
path: |
108-
logs
109-
.snakemake/log
110-
results
111-
retention-days: 3
34+
- uses: actions/checkout@v4
35+
with:
36+
repository: PyPSA/pypsa-eur
37+
ref: master
38+
39+
- name: Check out latest release
40+
if: matrix.version == 'latest'
41+
run: |
42+
git fetch --tags
43+
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
44+
git checkout $latest_tag
45+
46+
# Only run check if package is not pinned
47+
- name: Check if inhouse package is pinned
48+
run: |
49+
grep_line=$(grep -- '- pypsa' envs/environment.yaml)
50+
if [[ $grep_line == *"<"* || $grep_line == *"=="* ]]; then
51+
echo "pinned=true" >> $GITHUB_ENV
52+
else
53+
echo "pinned=false" >> $GITHUB_ENV
54+
fi
55+
56+
- name: Setup secrets & cache dates
57+
if: env.pinned == 'false'
58+
run: |
59+
echo -ne "url: ${CDSAPI_URL}\nkey: ${CDSAPI_TOKEN}\n" > ~/.cdsapirc
60+
echo "week=$(date +'%Y%U')" >> $GITHUB_ENV # data and cutouts
61+
62+
- uses: actions/cache@v4
63+
if: env.pinned == 'false'
64+
with:
65+
path: |
66+
data
67+
cutouts
68+
key: data-cutouts-${{ env.week }}
69+
70+
- uses: conda-incubator/setup-miniconda@v3
71+
if: env.pinned == 'false'
72+
with:
73+
activate-environment: pypsa-eur
74+
75+
- name: Cache Conda env
76+
if: env.pinned == 'false'
77+
uses: actions/cache@v4
78+
with:
79+
path: ${{ env.CONDA }}/envs
80+
key: conda-pypsa-eur-${{ env.week }}-${{ hashFiles('envs/linux-64.lock.yaml') }}
81+
id: cache-env
82+
83+
- name: Update environment
84+
if: env.pinned == 'false' && steps.cache-env.outputs.cache-hit != 'true'
85+
run: conda env update -n pypsa-eur -f envs/linux-64.lock.yaml
86+
87+
- name: Install package from ref
88+
if: env.pinned == 'false'
89+
run: |
90+
python -m pip install git+https://github.com/${{ github.repository }}@${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
91+
92+
- name: Run snakemake test workflows
93+
if: env.pinned == 'false'
94+
run: |
95+
make test
96+
97+
- name: Run unit tests
98+
if: env.pinned == 'false'
99+
run: |
100+
make unit-test
101+
102+
- name: Upload artifacts
103+
if: env.pinned == 'false'
104+
uses: actions/upload-artifact@v4
105+
with:
106+
name: results-pypsa-eur-${{ matrix.version }}
107+
path: |
108+
logs
109+
.snakemake/log
110+
results
111+
retention-days: 3

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ benchmark/scripts/leftovers/
4444

4545
# Claude
4646
.claude/settings.local.json
47+
48+
# direnv
49+
.envrc

doc/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Version 0.5.6
1515

1616
* With this release, the package support for Python 3.9 was dropped and support for Python 3.10 was officially added.
1717

18+
* The selection of a single item in `__getitem__` now returns a `Variable` instead of a `ScalarVariable`.
19+
20+
1821
Version 0.5.5
1922
--------------
2023

linopy/solvers.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ def solve_problem_from_file(
460460

461461
# Use HiGHS to parse the problem file and find the set of variable names, needed to parse solution
462462
h = highspy.Highs()
463+
h.silent()
463464
h.readModel(path_to_string(problem_fn))
464465
variables = {v.name for v in h.getVariables()}
465466

@@ -755,11 +756,11 @@ def solve_problem_from_model(
755756
)
756757

757758
h = model.to_highspy(explicit_coordinate_names=explicit_coordinate_names)
759+
self._set_solver_params(h, log_fn)
758760

759761
return self._solve(
760762
h,
761763
solution_fn,
762-
log_fn,
763764
warmstart_fn,
764765
basis_fn,
765766
model=model,
@@ -804,23 +805,35 @@ def solve_problem_from_file(
804805

805806
problem_fn_ = path_to_string(problem_fn)
806807
h = highspy.Highs()
808+
self._set_solver_params(h, log_fn)
809+
807810
h.readModel(problem_fn_)
808811

809812
return self._solve(
810813
h,
811814
solution_fn,
812-
log_fn,
813815
warmstart_fn,
814816
basis_fn,
815817
io_api=read_io_api_from_problem_file(problem_fn),
816818
sense=read_sense_from_problem_file(problem_fn),
817819
)
818820

821+
def _set_solver_params(
822+
self,
823+
highs_solver: highspy.Highs,
824+
log_fn: Path | None = None,
825+
) -> None:
826+
if log_fn is not None:
827+
self.solver_options["log_file"] = path_to_string(log_fn)
828+
logger.info(f"Log file at {self.solver_options['log_file']}")
829+
830+
for k, v in self.solver_options.items():
831+
highs_solver.setOptionValue(k, v)
832+
819833
def _solve(
820834
self,
821835
h: highspy.Highs,
822836
solution_fn: Path | None = None,
823-
log_fn: Path | None = None,
824837
warmstart_fn: Path | None = None,
825838
basis_fn: Path | None = None,
826839
model: Model | None = None,
@@ -877,13 +890,6 @@ def _solve(
877890
highspy.HighsModelStatus.kUnknown: TerminationCondition.unknown,
878891
}
879892

880-
if log_fn is not None:
881-
self.solver_options["log_file"] = path_to_string(log_fn)
882-
logger.info(f"Log file at {self.solver_options['log_file']}")
883-
884-
for k, v in self.solver_options.items():
885-
h.setOptionValue(k, v)
886-
887893
if warmstart_fn is not None and warmstart_fn.suffix == ".sol":
888894
h.readSolution(path_to_string(warmstart_fn), 0)
889895
elif warmstart_fn:

linopy/variables.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -199,22 +199,9 @@ def __init__(
199199
def __getitem__(
200200
self, selector: list[int] | int | slice | tuple[int64, str_]
201201
) -> Variable | ScalarVariable:
202-
keys = selector if isinstance(selector, tuple) else (selector,)
203-
if all(map(pd.api.types.is_scalar, keys)):
204-
warn(
205-
"Accessing a single value with `Variable[...]` and return type "
206-
"ScalarVariable is deprecated. In future, this will return a Variable."
207-
"To get a ScalarVariable use `Variable.at[...]` instead.",
208-
FutureWarning,
209-
)
210-
return self.at[keys]
211-
212-
else:
213-
# return selected Variable
214-
data = Dataset(
215-
{k: self.data[k][selector] for k in self.data}, attrs=self.attrs
216-
)
217-
return self.__class__(data, self.model, self.name)
202+
# return selected Variable
203+
data = Dataset({k: self.data[k][selector] for k in self.data}, attrs=self.attrs)
204+
return self.__class__(data, self.model, self.name)
218205

219206
@property
220207
def attrs(self) -> dict[str, Hashable]:

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ include = ["linopy"]
9191
write_to = "linopy/version.py"
9292
version_scheme = "no-guess-dev"
9393

94+
[tool.pytest.ini_options]
95+
testpaths = ["test"]
96+
norecursedirs = ["dev-scripts", "doc", "examples", "benchmark"]
97+
9498
[tool.coverage.run]
9599
branch = true
96100
source = ["linopy"]

test/test_variable.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ def test_wrong_variable_init(m: Model, x: linopy.Variable) -> None:
7373

7474

7575
def test_variable_getter(x: linopy.Variable, z: linopy.Variable) -> None:
76-
with pytest.warns(FutureWarning):
77-
assert isinstance(x[0], linopy.variables.ScalarVariable)
78-
assert isinstance(z[0], linopy.variables.ScalarVariable)
76+
assert isinstance(x[0], linopy.variables.Variable)
7977

8078
assert isinstance(x.at[0], linopy.variables.ScalarVariable)
8179

0 commit comments

Comments
 (0)