Skip to content

Commit 0268324

Browse files
authored
update to Python 3.13 (#71)
* Update package, doc and workflow to use Python 3.13 as our official version * Modernize type hints for Python 3.13 (list, dict, | operator) * Modernize string formatting ('.format()' and '%') to f-strings * fix lint errors * Revert type hints to Python 3.9 compatible syntax Replace | operator with Union/Optional to support Python 3.9+. Keep modern list/dict syntax which works in Python 3.9+. * remove unused import * Fix Python 3.9 compatibility for generic type unions
1 parent d0f572d commit 0268324

26 files changed

+236
-235
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Set up Python
2020
uses: actions/setup-python@v5
2121
with:
22-
python-version: 3.9
22+
python-version: '3.13'
2323
- name: Install Python dependencies
2424
run: |
2525
python -m pip install .[lint]

.github/workflows/promote_package_to_production.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Setup python
2626
uses: actions/setup-python@v5
2727
with:
28-
python-version: '3.9'
28+
python-version: '3.13'
2929
- name: Download package from staging
3030
env:
3131
PIP_EXTRA_INDEX_URL: https://${{ secrets.STAGING_ARTIFACTORY_USERNAME }}:${{ secrets.STAGING_ARTIFACTORY_PASSWORD }}@packages.idmod.org/api/pypi/idm-pypi-staging/simple/

.github/workflows/staging-build-package.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Setup python
2424
uses: actions/setup-python@v5
2525
with:
26-
python-version: '3.9'
26+
python-version: '3.13'
2727
- name: Install dependencies
2828
run: |
2929
python -m pip install .[packaging]

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
[![Lint](https://github.com/EMOD-Hub/emod-api/actions/workflows/lint.yml/badge.svg?branch=main)](https://github.com/EMOD-Hub/emod-api/actions/workflows/lint.yml)
55
[![Test and deploy to staging](https://github.com/EMOD-Hub/emod-api/actions/workflows/test_and_publish_package_to_staging.yml/badge.svg?branch=main)](https://github.com/EMOD-Hub/emod-api/actions/workflows/test_and_publish_package_to_staging.yml)
66

7+
## Python Version
8+
9+
Python 3.13 is the recommended and supported version.
10+
711
## Documentation
812

913
Documentation available at https://emod-hub.github.io/emod-api/.

docs/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ See the [idmtools documentation][idmtools] for a diagram of how each of the rela
1010

1111
## Installation
1212

13+
### Python Version
14+
15+
Python 3.13 is the recommended and supported version.
16+
17+
### Installing the Package
18+
1319
The emod-api package is currently available on a [Python package index server][idm_pypi] managed by the [Institute for Disease Modeling][idmod].
1420

1521
```

emod_api/campaign.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def get_event(event, old=False):
164164
return_event = event_map[event]
165165
else:
166166
# get next entry in GP_EVENT_xxx
167-
new_event_name = event if old else 'GP_EVENT_{:03d}'.format(len(event_map))
167+
new_event_name = event if old else f'GP_EVENT_{len(event_map):03d}'
168168
event_map[event] = new_event_name
169169
return_event = event_map[event]
170170
return return_event

emod_api/channelreports/channels.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from datetime import datetime
66
import json
77
from pathlib import Path
8-
from typing import Dict, List, Union
8+
from typing import Union
99
import pandas as pd
1010

1111
_CHANNELS = "Channels"
@@ -160,7 +160,7 @@ def num_time_steps(self, count: int) -> None:
160160
assert self._numTimeSteps > 0, "numTimeSteps must be > 0"
161161
return
162162

163-
def as_dictionary(self) -> Dict:
163+
def as_dictionary(self) -> dict:
164164
# https://stackoverflow.com/questions/38987/how-do-i-merge-two-dictionaries-in-a-single-expression
165165
return {
166166
**{
@@ -179,7 +179,7 @@ def as_dictionary(self) -> Dict:
179179

180180
class Channel(object):
181181

182-
def __init__(self, title: str, units: str, data: List) -> None:
182+
def __init__(self, title: str, units: str, data: list) -> None:
183183
self._title = title
184184
self._units = units
185185
self._data = data
@@ -216,7 +216,7 @@ def __setitem__(self, key, value) -> None:
216216
self._data[key] = value
217217
return
218218

219-
def as_dictionary(self) -> Dict:
219+
def as_dictionary(self) -> dict:
220220
return {self.title: {_UNITS: self.units, _DATA: list(self.data)}}
221221

222222

@@ -316,11 +316,11 @@ def num_channels(self) -> int:
316316
return len(self._channels)
317317

318318
@property
319-
def channel_names(self) -> List:
319+
def channel_names(self) -> list:
320320
return sorted(self._channels)
321321

322322
@property
323-
def channels(self) -> Dict:
323+
def channels(self) -> dict:
324324
"""Channel objects keyed on channel name/title"""
325325
return self._channels
326326

@@ -407,7 +407,7 @@ def validate_channel(_channel, _title, _header) -> None:
407407

408408
return
409409

410-
def to_csv(self, filename: Union[str, Path], channel_names: List[str] = None, transpose: bool = False) -> None:
410+
def to_csv(self, filename: Union[str, Path], channel_names: list[str] = None, transpose: bool = False) -> None:
411411

412412
"""
413413
Write each channel from the report to a row, CSV style, in the given file.

emod_api/channelreports/plot_prop_report.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from functools import reduce
77
import json
88
from pathlib import Path
9-
from typing import Dict, List
109

1110
import matplotlib.pyplot as plt
1211
import numpy as np
@@ -49,7 +48,7 @@ def main(args: argparse.Namespace):
4948
return
5049

5150

52-
def list_channels_and_ips(channel_keys: List[str]) -> None:
51+
def list_channels_and_ips(channel_keys: list[str]) -> None:
5352

5453
"""
5554
List the channels and properties found in a property report from the
@@ -79,7 +78,7 @@ def list_channels_and_ips(channel_keys: List[str]) -> None:
7978

8079

8180
def call_plot_traces(args: argparse.Namespace,
82-
trace_values: Dict[str, np.ndarray]) -> None:
81+
trace_values: dict[str, np.ndarray]) -> None:
8382

8483
"""
8584
Call the internal `plot_traces` function and, optionally, save the results to disk.

emod_api/channelreports/utils.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import json
66
from pathlib import Path
7-
from typing import Dict, List, Optional, Union
7+
from typing import Union, Optional
88

99
import matplotlib.pyplot as plt
1010
import numpy as np
@@ -27,8 +27,8 @@
2727

2828
def property_report_to_csv(source_file: Union[str, Path],
2929
csv_file: Union[str, Path],
30-
channels: Optional[List[str]] = None,
31-
groupby: Optional[List[str]] = None,
30+
channels: Optional[list[str]] = None,
31+
groupby: Optional[list[str]] = None,
3232
transpose: bool = False) -> None:
3333

3434
"""
@@ -66,15 +66,15 @@ def property_report_to_csv(source_file: Union[str, Path],
6666
return
6767

6868

69-
def read_json_file(filename: Union[str, Path]) -> Dict:
69+
def read_json_file(filename: Union[str, Path]) -> dict:
7070

7171
with Path(filename).open("r", encoding="utf-8") as file:
7272
json_data = json.load(file)
7373

7474
return json_data
7575

7676

77-
def get_report_channels(json_data: Dict) -> Dict:
77+
def get_report_channels(json_data: dict) -> dict:
7878

7979
try:
8080
channel_data = json_data['Channels']
@@ -112,7 +112,7 @@ def _validate_property_report_ips(groupby, channel_data) -> None:
112112
return
113113

114114

115-
def accumulate_channel_data(channels: List[str], verbose: bool, groupby: List[str], channel_data: Dict) -> Dict[str, np.ndarray]:
115+
def accumulate_channel_data(channels: list[str], verbose: bool, groupby: list[str], channel_data: dict) -> dict[str, np.ndarray]:
116116

117117
"""
118118
Extract selected channel(s) from property report data.
@@ -156,7 +156,7 @@ def accumulate_channel_data(channels: List[str], verbose: bool, groupby: List[st
156156
return trace_values
157157

158158

159-
def __get_trace_name(channel_title: str, key_value_pairs: List[str], groupby: List[str]) -> str:
159+
def __get_trace_name(channel_title: str, key_value_pairs: list[str], groupby: list[str]) -> str:
160160

161161
"""
162162
Return "canonical" trace name for a given channel, IP:value list, and groupby list.
@@ -197,7 +197,7 @@ def __get_trace_name(channel_title: str, key_value_pairs: List[str], groupby: Li
197197
return trace_name
198198

199199

200-
def save_to_csv(trace_values: Dict[str, np.ndarray],
200+
def save_to_csv(trace_values: dict[str, np.ndarray],
201201
filename: Union[str, Path],
202202
transpose: bool = False) -> None:
203203

@@ -220,10 +220,10 @@ def save_to_csv(trace_values: Dict[str, np.ndarray],
220220
return
221221

222222

223-
def plot_traces(trace_values: Dict[str, np.ndarray],
224-
norm_values: Optional[Union[int, np.ndarray]],
223+
def plot_traces(trace_values: dict[str, np.ndarray],
224+
norm_values: Union[int, np.ndarray, None],
225225
overlay: bool,
226-
channels: List[str],
226+
channels: list[str],
227227
title: str,
228228
legend: bool) -> plt.Figure:
229229

@@ -291,7 +291,7 @@ def plot_traces(trace_values: Dict[str, np.ndarray],
291291
return figure
292292

293293

294-
def __index_for(trace_name: str, channels: List[str], trace_keys: List[str], normalize: bool, overlay: bool) -> int:
294+
def __index_for(trace_name: str, channels: list[str], trace_keys: list[str], normalize: bool, overlay: bool) -> int:
295295

296296
if overlay:
297297
# all pools of the same channel overlaid
@@ -312,7 +312,7 @@ def __index_for(trace_name: str, channels: List[str], trace_keys: List[str], nor
312312
return index + 1
313313

314314

315-
def __title_for(trace_name: str, channels: List[str], overlay: bool):
315+
def __title_for(trace_name: str, channels: list[str], overlay: bool):
316316

317317
# use channel name
318318
if overlay:

emod_api/config/default_from_schema_no_validation.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
import json
44
import os
5+
from typing import Union
56
import warnings
67
import emod_api.schema_to_class as s2c
78

8-
from typing import Union
9-
109

1110
def _set_defaults_for_schema_group(dc_param,
1211
schema_section,

0 commit comments

Comments
 (0)