Skip to content

Commit 54a0416

Browse files
authored
Merge pull request #808 from amas0/develop
Remove Python 3.8 support
2 parents b3c6c47 + 5b92e35 commit 54a0416

24 files changed

+251
-261
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
strategy:
4545
matrix:
4646
os: [ubuntu-latest, macos-latest, windows-latest]
47-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
47+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
4848
env:
4949
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
5050
steps:

cmdstanpy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ def _cleanup_tmpdir() -> None:
3737
from .utils import (
3838
cmdstan_path,
3939
cmdstan_version,
40+
disable_logging,
41+
enable_logging,
4042
install_cmdstan,
4143
set_cmdstan_path,
4244
set_make_env,
4345
show_versions,
4446
write_stan_json,
45-
enable_logging,
46-
disable_logging,
4747
)
4848

4949
__all__ = [

cmdstanpy/cmdstan_args.py

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""
22
CmdStan arguments
33
"""
4+
45
import os
56
from enum import Enum, auto
67
from time import time
7-
from typing import Any, Dict, List, Mapping, Optional, Union
8+
from typing import Any, Mapping, Optional, Union
89

910
import numpy as np
1011
from numpy.random import default_rng
@@ -65,9 +66,9 @@ def __init__(
6566
thin: Optional[int] = None,
6667
max_treedepth: Optional[int] = None,
6768
metric: Union[
68-
str, Dict[str, Any], List[str], List[Dict[str, Any]], None
69+
str, dict[str, Any], list[str], list[dict[str, Any]], None
6970
] = None,
70-
step_size: Union[float, List[float], None] = None,
71+
step_size: Union[float, list[float], None] = None,
7172
adapt_engaged: bool = True,
7273
adapt_delta: Optional[float] = None,
7374
adapt_init_phase: Optional[int] = None,
@@ -84,7 +85,7 @@ def __init__(
8485
self.max_treedepth = max_treedepth
8586
self.metric = metric
8687
self.metric_type: Optional[str] = None
87-
self.metric_file: Union[str, List[str], None] = None
88+
self.metric_file: Union[str, list[str], None] = None
8889
self.step_size = step_size
8990
self.adapt_engaged = adapt_engaged
9091
self.adapt_delta = adapt_delta
@@ -161,8 +162,9 @@ def validate(self, chains: Optional[int]) -> None:
161162
):
162163
if self.step_size <= 0:
163164
raise ValueError(
164-
'Argument "step_size" must be > 0, '
165-
'found {}.'.format(self.step_size)
165+
'Argument "step_size" must be > 0, found {}.'.format(
166+
self.step_size
167+
)
166168
)
167169
else:
168170
if len(self.step_size) != chains:
@@ -217,9 +219,9 @@ def validate(self, chains: Optional[int]) -> None:
217219
)
218220
)
219221
if all(isinstance(elem, dict) for elem in self.metric):
220-
metric_files: List[str] = []
222+
metric_files: list[str] = []
221223
for i, metric in enumerate(self.metric):
222-
metric_dict: Dict[str, Any] = metric # type: ignore
224+
metric_dict: dict[str, Any] = metric # type: ignore
223225
if 'inv_metric' not in metric_dict:
224226
raise ValueError(
225227
'Entry "inv_metric" not found in metric dict '
@@ -343,7 +345,7 @@ def validate(self, chains: Optional[int]) -> None:
343345
'When fixed_param=True, cannot specify adaptation parameters.'
344346
)
345347

346-
def compose(self, idx: int, cmd: List[str]) -> List[str]:
348+
def compose(self, idx: int, cmd: list[str]) -> list[str]:
347349
"""
348350
Compose CmdStan command for method-specific non-default arguments.
349351
"""
@@ -467,7 +469,7 @@ def validate(self, _chains: Optional[int] = None) -> None:
467469
positive_float(self.tol_param, 'tol_param')
468470
positive_int(self.history_size, 'history_size')
469471

470-
def compose(self, _idx: int, cmd: List[str]) -> List[str]:
472+
def compose(self, _idx: int, cmd: list[str]) -> list[str]:
471473
"""compose command string for CmdStan for non-default arg values."""
472474
cmd.append('method=optimize')
473475
if self.algorithm:
@@ -511,7 +513,7 @@ def validate(self, _chains: Optional[int] = None) -> None:
511513
raise ValueError(f'Invalid path for mode file: {self.mode}')
512514
positive_int(self.draws, 'draws')
513515

514-
def compose(self, _idx: int, cmd: List[str]) -> List[str]:
516+
def compose(self, _idx: int, cmd: list[str]) -> list[str]:
515517
"""compose command string for CmdStan for non-default arg values."""
516518
cmd.append('method=laplace')
517519
cmd.append(f'mode={self.mode}')
@@ -579,7 +581,7 @@ def validate(self, _chains: Optional[int] = None) -> None:
579581
positive_int(self.num_draws, 'num_draws')
580582
positive_int(self.num_elbo_draws, 'num_elbo_draws')
581583

582-
def compose(self, _idx: int, cmd: List[str]) -> List[str]:
584+
def compose(self, _idx: int, cmd: list[str]) -> list[str]:
583585
"""compose command string for CmdStan for non-default arg values."""
584586
cmd.append('method=pathfinder')
585587

@@ -624,12 +626,13 @@ def compose(self, _idx: int, cmd: List[str]) -> List[str]:
624626
class GenerateQuantitiesArgs:
625627
"""Arguments needed for generate_quantities method."""
626628

627-
def __init__(self, csv_files: List[str]) -> None:
629+
def __init__(self, csv_files: list[str]) -> None:
628630
"""Initialize object."""
629631
self.sample_csv_files = csv_files
630632

631633
def validate(
632-
self, chains: Optional[int] = None # pylint: disable=unused-argument
634+
self,
635+
chains: Optional[int] = None, # pylint: disable=unused-argument
633636
) -> None:
634637
"""
635638
Check arguments correctness and consistency.
@@ -642,7 +645,7 @@ def validate(
642645
'Invalid path for sample csv file: {}'.format(csv)
643646
)
644647

645-
def compose(self, idx: int, cmd: List[str]) -> List[str]:
648+
def compose(self, idx: int, cmd: list[str]) -> list[str]:
646649
"""
647650
Compose CmdStan command for method-specific non-default arguments.
648651
"""
@@ -681,7 +684,8 @@ def __init__(
681684
self.output_samples = output_samples
682685

683686
def validate(
684-
self, chains: Optional[int] = None # pylint: disable=unused-argument
687+
self,
688+
chains: Optional[int] = None, # pylint: disable=unused-argument
685689
) -> None:
686690
"""
687691
Check arguments correctness and consistency.
@@ -705,7 +709,7 @@ def validate(
705709
positive_int(self.output_samples, 'output_samples')
706710

707711
# pylint: disable=unused-argument
708-
def compose(self, idx: int, cmd: List[str]) -> List[str]:
712+
def compose(self, idx: int, cmd: list[str]) -> list[str]:
709713
"""
710714
Compose CmdStan command for method-specific non-default arguments.
711715
"""
@@ -747,7 +751,7 @@ def __init__(
747751
self,
748752
model_name: str,
749753
model_exe: OptionalPath,
750-
chain_ids: Optional[List[int]],
754+
chain_ids: Optional[list[int]],
751755
method_args: Union[
752756
SamplerArgs,
753757
OptimizeArgs,
@@ -757,8 +761,8 @@ def __init__(
757761
PathfinderArgs,
758762
],
759763
data: Union[Mapping[str, Any], str, None] = None,
760-
seed: Union[int, List[int], None] = None,
761-
inits: Union[int, float, str, List[str], None] = None,
764+
seed: Union[int, list[int], None] = None,
765+
inits: Union[int, float, str, list[str], None] = None,
762766
output_dir: OptionalPath = None,
763767
sig_figs: Optional[int] = None,
764768
save_latent_dynamics: bool = False,
@@ -959,11 +963,11 @@ def compose_command(
959963
*,
960964
diagnostic_file: Optional[str] = None,
961965
profile_file: Optional[str] = None,
962-
) -> List[str]:
966+
) -> list[str]:
963967
"""
964968
Compose CmdStan command for non-default arguments.
965969
"""
966-
cmd: List[str] = []
970+
cmd: list[str] = []
967971
if idx is not None and self.chain_ids is not None:
968972
if idx < 0 or idx > len(self.chain_ids) - 1:
969973
raise ValueError(

cmdstanpy/compilation.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from copy import copy
1212
from datetime import datetime
1313
from pathlib import Path
14-
from typing import Any, Dict, Iterable, List, Optional, Union
14+
from typing import Any, Iterable, Optional, Union
1515

1616
from cmdstanpy.utils import get_logger
1717
from cmdstanpy.utils.cmdstan import (
@@ -81,8 +81,8 @@ class CompilerOptions:
8181
def __init__(
8282
self,
8383
*,
84-
stanc_options: Optional[Dict[str, Any]] = None,
85-
cpp_options: Optional[Dict[str, Any]] = None,
84+
stanc_options: Optional[dict[str, Any]] = None,
85+
cpp_options: Optional[dict[str, Any]] = None,
8686
user_header: OptionalPath = None,
8787
) -> None:
8888
"""Initialize object."""
@@ -116,12 +116,12 @@ def is_empty(self) -> bool:
116116
)
117117

118118
@property
119-
def stanc_options(self) -> Dict[str, Union[bool, int, str, Iterable[str]]]:
119+
def stanc_options(self) -> dict[str, Union[bool, int, str, Iterable[str]]]:
120120
"""Stanc compiler options."""
121121
return self._stanc_options
122122

123123
@property
124-
def cpp_options(self) -> Dict[str, Union[bool, int]]:
124+
def cpp_options(self) -> dict[str, Union[bool, int]]:
125125
"""C++ compiler options."""
126126
return self._cpp_options
127127

@@ -165,8 +165,8 @@ def validate_stanc_opts(self) -> None:
165165
del self._stanc_options[deprecated]
166166
else:
167167
get_logger().warning(
168-
'compiler option "%s" is deprecated and '
169-
'should not be used',
168+
'compiler option "%s" is deprecated and should '
169+
'not be used',
170170
deprecated,
171171
)
172172
for key, val in self._stanc_options.items():
@@ -225,8 +225,8 @@ def validate_cpp_opts(self) -> None:
225225
val = self._cpp_options[key]
226226
if not isinstance(val, int) or val < 0:
227227
raise ValueError(
228-
f'{key} must be a non-negative integer value,'
229-
f' found {val}.'
228+
f'{key} must be a non-negative integer '
229+
f'value, found {val}.'
230230
)
231231

232232
def validate_user_header(self) -> None:
@@ -298,7 +298,7 @@ def add_include_path(self, path: str) -> None:
298298
elif path not in self._stanc_options['include-paths']:
299299
self._stanc_options['include-paths'].append(path)
300300

301-
def compose_stanc(self, filename_in_msg: Optional[str]) -> List[str]:
301+
def compose_stanc(self, filename_in_msg: Optional[str]) -> list[str]:
302302
opts = []
303303

304304
if filename_in_msg is not None:
@@ -322,7 +322,7 @@ def compose_stanc(self, filename_in_msg: Optional[str]) -> List[str]:
322322
opts.append(f'--{key}')
323323
return opts
324324

325-
def compose(self, filename_in_msg: Optional[str] = None) -> List[str]:
325+
def compose(self, filename_in_msg: Optional[str] = None) -> list[str]:
326326
"""
327327
Format makefile options as list of strings.
328328
@@ -344,7 +344,7 @@ def compose(self, filename_in_msg: Optional[str] = None) -> List[str]:
344344

345345
def src_info(
346346
stan_file: str, compiler_options: CompilerOptions
347-
) -> Dict[str, Any]:
347+
) -> dict[str, Any]:
348348
"""
349349
Get source info for Stan program file.
350350
@@ -363,15 +363,15 @@ def src_info(
363363
f"Failed to get source info for Stan model "
364364
f"'{stan_file}'. Console:\n{proc.stderr}"
365365
)
366-
result: Dict[str, Any] = json.loads(proc.stdout)
366+
result: dict[str, Any] = json.loads(proc.stdout)
367367
return result
368368

369369

370370
def compile_stan_file(
371371
src: Union[str, Path],
372372
force: bool = False,
373-
stanc_options: Optional[Dict[str, Any]] = None,
374-
cpp_options: Optional[Dict[str, Any]] = None,
373+
stanc_options: Optional[dict[str, Any]] = None,
374+
cpp_options: Optional[dict[str, Any]] = None,
375375
user_header: OptionalPath = None,
376376
) -> str:
377377
"""
@@ -480,7 +480,7 @@ def compile_stan_file(
480480
"If the issue persists please open a bug report"
481481
)
482482
raise ValueError(
483-
f"Failed to compile Stan model '{src}'. " f"Console:\n{console}"
483+
f"Failed to compile Stan model '{src}'. Console:\n{console}"
484484
)
485485
return str(exe_target)
486486

@@ -492,7 +492,7 @@ def format_stan_file(
492492
canonicalize: Union[bool, str, Iterable[str]] = False,
493493
max_line_length: int = 78,
494494
backup: bool = True,
495-
stanc_options: Optional[Dict[str, Any]] = None,
495+
stanc_options: Optional[dict[str, Any]] = None,
496496
) -> None:
497497
"""
498498
Run stanc's auto-formatter on the model code. Either saves directly

cmdstanpy/install_cmdstan.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
--cores: int, number of cores to use when building, defaults to 1
1818
-c, --compiler : flag, add C++ compiler to path (Windows only)
1919
"""
20+
2021
import argparse
2122
import json
2223
import os
@@ -30,7 +31,7 @@
3031
from collections import OrderedDict
3132
from pathlib import Path
3233
from time import sleep
33-
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union
34+
from typing import TYPE_CHECKING, Any, Callable, Optional, Union
3435

3536
from tqdm.auto import tqdm
3637

@@ -85,7 +86,7 @@ def is_windows() -> bool:
8586
EXTENSION = '.exe' if is_windows() else ''
8687

8788

88-
def get_headers() -> Dict[str, str]:
89+
def get_headers() -> dict[str, str]:
8990
"""Create headers dictionary."""
9091
headers = {}
9192
GITHUB_PAT = os.environ.get("GITHUB_PAT") # pylint:disable=invalid-name
@@ -287,13 +288,13 @@ def build(verbose: bool = False, progress: bool = True, cores: int = 1) -> None:
287288
raise CmdStanInstallError(f'Command "make build" failed\n{str(e)}')
288289
if not os.path.exists(os.path.join('bin', 'stansummary' + EXTENSION)):
289290
raise CmdStanInstallError(
290-
f'bin/stansummary{EXTENSION} not found'
291-
', please rebuild or report a bug!'
291+
f'bin/stansummary{EXTENSION} not found, please rebuild or '
292+
'report a bug!'
292293
)
293294
if not os.path.exists(os.path.join('bin', 'diagnose' + EXTENSION)):
294295
raise CmdStanInstallError(
295-
f'bin/stansummary{EXTENSION} not found'
296-
', please rebuild or report a bug!'
296+
f'bin/stansummary{EXTENSION} not found, please rebuild or '
297+
'report a bug!'
297298
)
298299

299300
if is_windows():
@@ -417,8 +418,8 @@ def install_version(
417418
)
418419
if overwrite and os.path.exists('.'):
419420
print(
420-
'Overwrite requested, remove existing build of version '
421-
'{}'.format(cmdstan_version)
421+
'Overwrite requested, remove existing build '
422+
'of version {}'.format(cmdstan_version)
422423
)
423424
clean_all(verbose)
424425
print('Rebuilding version {}'.format(cmdstan_version))
@@ -496,10 +497,8 @@ def retrieve_version(version: str, progress: bool = True) -> None:
496497
break
497498
except urllib.error.HTTPError as e:
498499
raise CmdStanRetrieveError(
499-
'HTTPError: {}\n'
500-
'Version {} not available from github.com.'.format(
501-
e.code, version
502-
)
500+
'HTTPError: {}\nVersion {} not available from '
501+
'github.com.'.format(e.code, version)
503502
) from e
504503
except urllib.error.URLError as e:
505504
print(
@@ -645,7 +644,7 @@ def run_install(args: Union[InteractiveSettings, InstallationSettings]) -> None:
645644
compile_example(args.verbose)
646645

647646

648-
def parse_cmdline_args() -> Dict[str, Any]:
647+
def parse_cmdline_args() -> dict[str, Any]:
649648
parser = argparse.ArgumentParser("install_cmdstan")
650649
parser.add_argument(
651650
'--interactive',

0 commit comments

Comments
 (0)