Skip to content

Commit e154795

Browse files
committed
feat: add Python type hinting and annotations
Signed-off-by: Davide Madrisan <[email protected]>
1 parent e8a6faa commit e154795

File tree

4 files changed

+44
-34
lines changed

4 files changed

+44
-34
lines changed

hadcrut5_bars.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
Display a bar plot of the HadCRUT5 Global temperature dataset.
77
"""
88

9+
import argparse
10+
911
import matplotlib.pyplot as plt
1012
import matplotlib.colors
1113

1214
from hadcrut5lib import argparser, HadCRUT5
1315

1416

15-
def parse_args():
17+
def parse_args() -> argparse.Namespace:
1618
"""This function parses and return arguments passed in"""
1719
descr = "Parse and plot the HadCRUT5 temperature datasets"
1820
examples = [
@@ -49,7 +51,8 @@ def parse_args():
4951
return parser.parse_args()
5052

5153

52-
def plotbar(period, outfile, verbose):
54+
# mypy: disable-error-code="misc, attr-defined"
55+
def plotbar(period: str, outfile: str, verbose: bool):
5356
"""
5457
Create a bar plot for the specified period and diplay it or save it to file
5558
if outfile is set
@@ -81,7 +84,8 @@ def major_formatter(x, pos):
8184
plt.style.use("dark_background")
8285
_, ax = plt.subplots()
8386

84-
cmap = plt.cm.jet # or plt.cm.bwr # pylint: disable=no-member
87+
# pylint: disable=no-member
88+
cmap = plt.cm.jet # or plt.cm.bwr
8589
norm = matplotlib.colors.Normalize(vmin=-1, vmax=max(mean))
8690
colors = cmap(norm(mean))
8791

hadcrut5_plot.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
Display a plot of the HadCRUT5 temperature dataset.
77
"""
88

9+
import argparse
910
from math import trunc
11+
from typing import List
1012

1113
import matplotlib as mpl
1214
import matplotlib.pyplot as plt
@@ -15,7 +17,7 @@
1517
from hadcrut5lib import argparser, HadCRUT5
1618

1719

18-
def parse_args():
20+
def parse_args() -> argparse.Namespace:
1921
"""This function parses and return arguments passed in"""
2022
descr = "Parse and plot the HadCRUT5 temperature datasets"
2123
examples = [
@@ -99,17 +101,17 @@ def parse_args():
99101
return parser.parse_args()
100102

101103

102-
def dataset_current_anomaly(temperatures):
104+
def dataset_current_anomaly(temperatures: List[float]) -> float:
103105
"""Return the current anomaly"""
104106
return temperatures[-1]
105107

106108

107-
def dataset_max_anomaly(temperatures):
109+
def dataset_max_anomaly(temperatures: List[float]) -> float:
108110
"""Return the maximum anomaly with respect to 'temperatures'"""
109111
return np.max(temperatures)
110112

111113

112-
def dataset_smoother(years, temperatures, chunksize):
114+
def dataset_smoother(years: List[int | float], temperatures: List[float], chunksize: int):
113115
"""Make the lines smoother by using {chunksize}-year means"""
114116
data_range = range((len(years) + chunksize - 1) // chunksize)
115117
subset_years = [years[i * chunksize] for i in data_range]
@@ -120,7 +122,7 @@ def dataset_smoother(years, temperatures, chunksize):
120122
return subset_years, subset_temperatures
121123

122124

123-
def plotline(hc5, chunksize, annotate, outfile):
125+
def plotline(hc5: HadCRUT5, chunksize: int, annotate: int, outfile: str):
124126
"""
125127
Create a plot for the specified period and arguments and diplay it or save
126128
it to file if outfile is set

hadcrut5_stripe.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
Display a stripe image of the HadCRUT5 Global temperature dataset.
77
"""
88

9+
import argparse
10+
from typing import List
11+
912
import matplotlib.pyplot as plt
1013
from matplotlib.collections import PatchCollection
1114
from matplotlib.colors import ListedColormap
@@ -14,7 +17,7 @@
1417
from hadcrut5lib import argparser, HadCRUT5
1518

1619

17-
def parse_args():
20+
def parse_args() -> argparse.Namespace:
1821
"""This function parses and return arguments passed in"""
1922
descr = "Parse and plot a stripe image of the HadCRUT5 temperature datasets"
2023
examples = [
@@ -59,7 +62,7 @@ def parse_args():
5962
return parser.parse_args()
6063

6164

62-
def plotstripe(region, outfile, labels, verbose):
65+
def plotstripe(region: str, outfile: str, labels: bool, verbose: bool):
6366
"""
6467
Create a stripe plot for the specified period and diplay it or save it to
6568
file if outfile is set
@@ -74,7 +77,7 @@ def plotstripe(region, outfile, labels, verbose):
7477

7578
years = hc5.dataset_years()
7679
yfirst, ylast = years[0], years[-1]
77-
yrange = ylast - yfirst
80+
yrange = int(ylast - yfirst)
7881

7982
regions_switch = {
8083
"global": hc5.GLOBAL_REGION,
@@ -134,7 +137,7 @@ def plotstripe(region, outfile, labels, verbose):
134137
)
135138

136139
ticks = [0, 0.2, 0.4, 0.6, 0.8, 1]
137-
xlabels = [round(yfirst + x * yrange) for x in ticks]
140+
xlabels: List[str] = [str(round(yfirst + x * yrange)) for x in ticks]
138141
plt.xticks(ticks, xlabels, fontweight="bold", fontsize=12)
139142
else:
140143
ax.get_xaxis().set_visible(False)

hadcrut5lib.py

+23-22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import json
1212
import logging
1313
import sys
14+
from typing import Dict, List, Mapping, Tuple
1415

1516
import numpy as np
1617
import requests
@@ -28,15 +29,15 @@
2829
__status__ = "stable"
2930

3031

31-
def copyleft(descr):
32+
def copyleft(descr: str) -> str:
3233
"""Print the Copyright message and License"""
3334
return (
3435
f"{descr} v{__version__} ({__status__})\n"
3536
"{__copyright__} <{__email__}>\nLicense: {__license__}"
3637
)
3738

3839

39-
def argparser(descr, examples):
40+
def argparser(descr: str, examples: List[str]) -> argparse.ArgumentParser:
4041
"""Return a new ArgumentParser object"""
4142
return argparse.ArgumentParser(
4243
formatter_class=argparse.RawDescriptionHelpFormatter,
@@ -49,16 +50,16 @@ def argparser(descr, examples):
4950
class HadCRUT5:
5051
"""Class for parsing and plotting HadCRUT5 datasets"""
5152

52-
# current dataset version
5353
_DATASET_VERSION = "5.0.2.0"
54+
"""current dataset version"""
5455

55-
# list of all the available data types
5656
_DEFAULT_DATATYPE = "annual"
5757
_VALID_DATATYPES = [_DEFAULT_DATATYPE, "monthly"]
58+
"""list of all the available data types"""
5859

59-
# list of all the valid periods
6060
_DEFAULT_PERIOD = "1961-1990"
6161
_VALID_PERIODS = [_DEFAULT_PERIOD, "1850-1900", "1880-1920"]
62+
"""list of all the valid periods"""
6263

6364
GLOBAL_REGION = "Global"
6465
NORTHERN_REGION = "Northern Hemisphere"
@@ -114,10 +115,10 @@ def datasets_download(self):
114115
if self._enable_southern:
115116
self._wget_dataset_file(self._southern_hemisphere_filename)
116117

117-
def datasets_load(self):
118+
def datasets_load(self) -> None:
118119
"""Load all the netCDFv4 datasets"""
119120

120-
def dataset_load(dataset_filename):
121+
def dataset_load(dataset_filename: str) -> Dict:
121122
"""Load the data provided by the netCDFv4 file 'dataset_filename'"""
122123
dataset = nc_Dataset(dataset_filename)
123124
return {
@@ -126,7 +127,7 @@ def dataset_load(dataset_filename):
126127
"variables": dataset.variables,
127128
}
128129

129-
def dataset_metadata_dump(dataset_name, dataset):
130+
def dataset_metadata_dump(dataset_name: str, dataset) -> None:
130131
metadata = dataset["metadata"]
131132
self.logging_debug(
132133
(f'Metadata for "{dataset_name}" dataset:\n{json.dumps(metadata, indent=2)}'),
@@ -145,14 +146,14 @@ def dataset_metadata_dump(dataset_name, dataset):
145146
self._datasets[region] = dataset_load(self._southern_hemisphere_filename)
146147
dataset_metadata_dump(region, self._datasets[region])
147148

148-
def datasets_normalize(self):
149+
def datasets_normalize(self) -> None:
149150
"""
150151
Normalize the temperature means to the required time period.
151152
Set _datasets_normalized with a tuple containing lower, mean, and upper
152153
temperatures for every enabled region
153154
"""
154155

155-
def normalization_value(temperatures):
156+
def normalization_value(temperatures: List[float]) -> float:
156157
"""
157158
Return the value to be substracted to temperatures in order to
158159
obtain a mean-centered dataset for the required period
@@ -176,7 +177,7 @@ def normalization_value(temperatures):
176177
raise ValueError(f'Unsupported period "{self._period}"')
177178

178179
self.logging_debug("The mean anomaly in {self._period} is about {norm_temp:.8f}°C")
179-
return norm_temp
180+
return float(norm_temp)
180181

181182
for region, data in self._datasets.items():
182183
mean = data["variables"]["tas_mean"]
@@ -196,26 +197,26 @@ def normalization_value(temperatures):
196197
f"normalized dataset ({region}): mean \\\n{np.array(mean) - norm_temp}"
197198
)
198199

199-
def datasets_regions(self):
200+
def datasets_regions(self) -> Mapping[str, object]:
200201
"""Return the dataset regions set by the user at command-line"""
201202
return self._datasets.keys()
202203

203-
def logging(self, message):
204+
def logging(self, message: str) -> None:
204205
"""Print a message"""
205206
logging.info(message)
206207

207-
def logging_debug(self, message):
208+
def logging_debug(self, message: str) -> None:
208209
"""Print a message when in verbose mode only"""
209210
if self._verbose:
210211
logging.info(message)
211212

212-
def _hadcrut5_data_url(self, filename):
213+
def _hadcrut5_data_url(self, filename: str) -> str:
213214
site = "https://www.metoffice.gov.uk"
214215
path = f"/hadobs/hadcrut5/data/HadCRUT.{self._DATASET_VERSION}/analysis/diagnostics/"
215216
url = f"{site}{path}{filename}"
216217
return url
217218

218-
def _wget_dataset_file(self, filename):
219+
def _wget_dataset_file(self, filename: str) -> None:
219220
"""Download a netCDFv4 HadCRUT5 file if not already found locally"""
220221
try:
221222
with open(filename, encoding="utf-8"):
@@ -240,31 +241,31 @@ def _wget_dataset_file(self, filename):
240241
handle.write(block)
241242

242243
@property
243-
def dataset_datatype(self):
244+
def dataset_datatype(self) -> str:
244245
"""Return the datatype string"""
245246
return self._datatype
246247

247248
@property
248-
def dataset_history(self):
249+
def dataset_history(self) -> str:
249250
"""Return the datatype history from metadata"""
250251
# The datasets have all the same length so choose the first one
251252
region = list(self._datasets.keys())[0]
252253
metadata = self._datasets[region]["metadata"]
253254
return metadata.get("history")
254255

255-
def dataset_normalized_data(self, region):
256+
def dataset_normalized_data(self, region) -> Tuple[List[float], List[float], List[float]]:
256257
"""Return the dataset data normalized for the specified region"""
257258
lower = self._datasets_normalized[region]["lower"]
258259
mean = self._datasets_normalized[region]["mean"]
259260
upper = self._datasets_normalized[region]["upper"]
260261
return (lower, mean, upper)
261262

262263
@property
263-
def dataset_period(self):
264+
def dataset_period(self) -> str:
264265
"""Return the dataset period as a string"""
265266
return self._period
266267

267-
def dataset_years(self):
268+
def dataset_years(self) -> List[int|float]:
268269
"""
269270
Return an array of years corresponding of the loaded datasets.
270271
If the original dataset packages monthly data, the returning vector
@@ -279,7 +280,7 @@ def dataset_years(self):
279280
return years
280281

281282
@property
282-
def is_monthly_dataset(self):
283+
def is_monthly_dataset(self) -> bool:
283284
"""
284285
Return True if the loaded dataset provide monthly data,
285286
False otherwise

0 commit comments

Comments
 (0)