GLODAP 0.3__tar.gz → 0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,24 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: glodap
3
- Version: 0.3
3
+ Version: 0.4
4
4
  Summary: GLODAP downloader and importer in Python
5
5
  Classifier: Development Status :: 4 - Beta
6
- Classifier: Programming Language :: Python :: 3.10
7
6
  Classifier: Programming Language :: Python :: 3.11
8
7
  Classifier: Programming Language :: Python :: 3.12
9
8
  Classifier: Programming Language :: Python :: 3.13
9
+ Classifier: Programming Language :: Python :: 3.14
10
10
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
11
  Classifier: Operating System :: OS Independent
12
12
  Classifier: Natural Language :: English
13
13
  Classifier: Intended Audience :: Science/Research
14
14
  Classifier: Topic :: Scientific/Engineering :: Chemistry
15
15
  Classifier: Topic :: Scientific/Engineering :: Oceanography
16
- Requires-Python: >=3.10
16
+ Requires-Python: >=3.11
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: pandas
20
- Requires-Dist: requests
21
- Requires-Dist: scipy
19
+ Requires-Dist: pandas<4,>=3.0.3
20
+ Requires-Dist: pooch<2,>=1.9.0
21
+ Requires-Dist: scipy<2,>=1.17.1
22
22
  Dynamic: license-file
23
23
 
24
24
  # glodap
@@ -53,15 +53,15 @@ directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
53
53
 
54
54
  ```python
55
55
  import PyCO2SYS as pyco2
56
- co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=None)
56
+ co2s_atlantic = pyco2.sys(data=df_atlantic.drop(columns="fco2"), nitrite=0)
57
57
  ```
58
58
 
59
- Note `nitrite=None` - this means PyCO2SYS will ignore the `"nitrite"` column,
59
+ Note `nitrite=0` - this means PyCO2SYS will ignore the `"nitrite"` column,
60
60
  which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
61
61
  equilibrium, its equilibrium constant is valid only under lab conditions.
62
62
 
63
- Because of how the columns are named, when passing the DataFrame directly to
64
- PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH.
63
+ Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
64
+ PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
65
65
 
66
66
  The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
67
67
  * The `"G2"` at the start of each parameter has been removed.
@@ -74,3 +74,15 @@ their function docstrings for more information.
74
74
 
75
75
  The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
76
76
  of each downloaded file is checked before the file is written to disk.
77
+
78
+ # Citation
79
+
80
+ If using GLODAP data, please cite the paper corresponding to the version you used:
81
+
82
+ * `v3.2026`: TBC (submitted to *Earth System Science Data*)
83
+ * `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
84
+ * `v2.2022`: https://doi.org/10.5194/essd-14-5543-2022
85
+ * `v2.2021`: https://doi.org/10.5194/essd-13-5565-2021
86
+ * `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
87
+ * `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
88
+ * `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
@@ -12,6 +12,5 @@ glodap.egg-info/SOURCES.txt
12
12
  glodap.egg-info/dependency_links.txt
13
13
  glodap.egg-info/requires.txt
14
14
  glodap.egg-info/top_level.txt
15
- tests/test_import.py
16
- tests/test_regions.py
17
- tests/test_response.py
15
+ tests/test_download_and_read.py
16
+ tests/test_regions.py
@@ -0,0 +1,3 @@
1
+ pandas<4,>=3.0.3
2
+ pooch<2,>=1.9.0
3
+ scipy<2,>=1.17.1
@@ -1,24 +1,24 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: glodap
3
- Version: 0.3
3
+ Version: 0.4
4
4
  Summary: GLODAP downloader and importer in Python
5
5
  Classifier: Development Status :: 4 - Beta
6
- Classifier: Programming Language :: Python :: 3.10
7
6
  Classifier: Programming Language :: Python :: 3.11
8
7
  Classifier: Programming Language :: Python :: 3.12
9
8
  Classifier: Programming Language :: Python :: 3.13
9
+ Classifier: Programming Language :: Python :: 3.14
10
10
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
11
  Classifier: Operating System :: OS Independent
12
12
  Classifier: Natural Language :: English
13
13
  Classifier: Intended Audience :: Science/Research
14
14
  Classifier: Topic :: Scientific/Engineering :: Chemistry
15
15
  Classifier: Topic :: Scientific/Engineering :: Oceanography
16
- Requires-Python: >=3.10
16
+ Requires-Python: >=3.11
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: pandas
20
- Requires-Dist: requests
21
- Requires-Dist: scipy
19
+ Requires-Dist: pandas<4,>=3.0.3
20
+ Requires-Dist: pooch<2,>=1.9.0
21
+ Requires-Dist: scipy<2,>=1.17.1
22
22
  Dynamic: license-file
23
23
 
24
24
  # glodap
@@ -53,15 +53,15 @@ directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
53
53
 
54
54
  ```python
55
55
  import PyCO2SYS as pyco2
56
- co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=None)
56
+ co2s_atlantic = pyco2.sys(data=df_atlantic.drop(columns="fco2"), nitrite=0)
57
57
  ```
58
58
 
59
- Note `nitrite=None` - this means PyCO2SYS will ignore the `"nitrite"` column,
59
+ Note `nitrite=0` - this means PyCO2SYS will ignore the `"nitrite"` column,
60
60
  which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
61
61
  equilibrium, its equilibrium constant is valid only under lab conditions.
62
62
 
63
- Because of how the columns are named, when passing the DataFrame directly to
64
- PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH.
63
+ Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
64
+ PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
65
65
 
66
66
  The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
67
67
  * The `"G2"` at the start of each parameter has been removed.
@@ -74,3 +74,15 @@ their function docstrings for more information.
74
74
 
75
75
  The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
76
76
  of each downloaded file is checked before the file is written to disk.
77
+
78
+ # Citation
79
+
80
+ If using GLODAP data, please cite the paper corresponding to the version you used:
81
+
82
+ * `v3.2026`: TBC (submitted to *Earth System Science Data*)
83
+ * `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
84
+ * `v2.2022`: https://doi.org/10.5194/essd-14-5543-2022
85
+ * `v2.2021`: https://doi.org/10.5194/essd-13-5565-2021
86
+ * `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
87
+ * `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
88
+ * `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
@@ -30,15 +30,15 @@ directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
30
30
 
31
31
  ```python
32
32
  import PyCO2SYS as pyco2
33
- co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=None)
33
+ co2s_atlantic = pyco2.sys(data=df_atlantic.drop(columns="fco2"), nitrite=0)
34
34
  ```
35
35
 
36
- Note `nitrite=None` - this means PyCO2SYS will ignore the `"nitrite"` column,
36
+ Note `nitrite=0` - this means PyCO2SYS will ignore the `"nitrite"` column,
37
37
  which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
38
38
  equilibrium, its equilibrium constant is valid only under lab conditions.
39
39
 
40
- Because of how the columns are named, when passing the DataFrame directly to
41
- PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH.
40
+ Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
41
+ PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
42
42
 
43
43
  The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
44
44
  * The `"G2"` at the start of each parameter has been removed.
@@ -51,3 +51,15 @@ their function docstrings for more information.
51
51
 
52
52
  The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
53
53
  of each downloaded file is checked before the file is written to disk.
54
+
55
+ # Citation
56
+
57
+ If using GLODAP data, please cite the paper corresponding to the version you used:
58
+
59
+ * `v3.2026`: TBC (submitted to *Earth System Science Data*)
60
+ * `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
61
+ * `v2.2022`: https://doi.org/10.5194/essd-14-5543-2022
62
+ * `v2.2021`: https://doi.org/10.5194/essd-13-5565-2021
63
+ * `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
64
+ * `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
65
+ * `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
@@ -1,8 +1,8 @@
1
1
  """
2
2
  GLODAP
3
3
  ======
4
- Download GLODAP (https://glodap.info) datasets and import them as pandas
5
- DataFrames.
4
+ Download Global Ocean Data Analysis Project (GLODAP; https://glodap.info)
5
+ datasets and import them as pandas DataFrames.
6
6
 
7
7
  The functions `arctic`, `atlantic`, `indian`, `pacific` and `world` import the
8
8
  latest version of the GLODAP dataset for the corresponding region, first
@@ -40,23 +40,32 @@ The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
40
40
  of each downloaded file is checked before the file is written to disk.
41
41
  """
42
42
 
43
- import hashlib
44
43
  import os
44
+ import shutil
45
45
  import tempfile
46
- from warnings import warn
46
+ from pathlib import Path
47
47
 
48
+ import numpy as np
48
49
  import pandas as pd
49
- import requests
50
+ import pooch
50
51
  from scipy.io import loadmat
51
52
 
52
53
 
53
54
  # Package metadata
54
55
  __author__ = "Humphreys, Matthew P."
55
- __version__ = "0.3"
56
+ __version__ = "0.4"
56
57
 
57
58
  # GLODAP metadata
58
- version_latest = "v2.2023"
59
- versions = ["v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"]
59
+ version_latest = "v3.2026"
60
+ versions = [
61
+ "v3.2026",
62
+ "v2.2023",
63
+ "v2.2022",
64
+ "v2.2021",
65
+ "v2.2020",
66
+ "v2.2019",
67
+ "v2.2016",
68
+ ]
60
69
  regions = {
61
70
  "arctic": "Arctic_Ocean",
62
71
  "atlantic": "Atlantic_Ocean",
@@ -67,7 +76,15 @@ regions = {
67
76
  regions_full = regions.copy()
68
77
  for k, v in regions.items():
69
78
  regions_full[k[:3]] = v
79
+ regions_short_to_long = {k[:3]: k for k in regions}
70
80
  checksums = {
81
+ "v3.2026": {
82
+ "arc": "03dfcf59525931065247e142439d97c0ed88d8f572e87df919476deebdc57d5c",
83
+ "atl": "a4577bbb676c30327b185fc5bf0ddc0e302464d5332b6d630922faf536dbe68c",
84
+ "ind": "79d655bd203e4579007b7224fc53b87ee8a5d70bb733550f0acac260a6baa0d8",
85
+ "pac": "1a5afbb6be199773e00772ca3b1b84241dfc52a591b3f6b85786180f5711a9b4",
86
+ "wor": "214aeb49c618474bf92622a37d2795a10160954ab49a94f9052cff1dd41947fd",
87
+ },
71
88
  "v2.2023": {
72
89
  "arc": "a998a8d99db84e9357b21a7e345bbfde62eae77870e651119b4c1929a2f1e2fd",
73
90
  "atl": "a3ff7bc4f4ff3a1b0f540886a0eb7c9b3ec52aa4eae2dea57d47ae61f56da56f",
@@ -103,6 +120,13 @@ checksums = {
103
120
  "pac": "88df995e272dd63db55421b911be1f99bfec4cac6f97a73e017c9e275bf29db2",
104
121
  "wor": "4637ce5eb560fe020e9fccf0370156bfe19498fc74c2e8b66dee190cc44cff63",
105
122
  },
123
+ "v2.2016": {
124
+ "arc": "f2214409e0526052903da2427f3f8c6fd433b1759ba2a1be3a61181b4b0d04b7",
125
+ "atl": "fb26a86ca1135a0afc94157ba7963bc1cb8138523bcba36360595641175f8da1",
126
+ "ind": "ba162aa6f1fa7209f586e503581d3cc05cdffbfa6f72bdc535824f7a78d694f9",
127
+ "pac": "0d1666de27ad6853533651027459d2525f75c6681d540f129df705b018d3c931",
128
+ "wor": "aa202e330d5e77b98d0062e40a40665b8397b83ebbfa00424532139c53814f5e",
129
+ },
106
130
  }
107
131
 
108
132
 
@@ -113,13 +137,16 @@ def _get_paths(region, version, gpath):
113
137
  version = version.lower()
114
138
  assert version in versions, "`version` not valid!"
115
139
  if gpath is None:
116
- gpath = os.path.join(os.path.expanduser("~"), ".glodap")
140
+ gpath = Path(Path.home(), ".glodap")
117
141
  fileregion = regions_full[region.lower()]
118
- filename = f"{fileregion}_{version}.mat"
142
+ if version.startswith("v2"):
143
+ filename = f"{fileregion}_{version}.mat"
144
+ elif version.startswith("v3"):
145
+ filename = f"{fileregion}_{version}.csv.zip"
119
146
  return gpath, fileregion, filename, version
120
147
 
121
148
 
122
- def download(region="world", version=None, gpath=None, chunk_size=8192):
149
+ def download(region="world", version=None, gpath=None):
123
150
  """Download a GLODAP data file and save it locally, after checking that it
124
151
  has the expected checksum (SHA256).
125
152
 
@@ -136,7 +163,13 @@ def download(region="world", version=None, gpath=None, chunk_size=8192):
136
163
  version : str or None, optional
137
164
  Which GLODAP version to download, by default `None`, in which case the
138
165
  most recent version is downloaded. The options are:
139
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
166
+ "v3.2026" (the original GLODAPv3)
167
+ "v2.2023",
168
+ "v2.2022",
169
+ "v2.2021",
170
+ "v2.2020",
171
+ "v2.2019",
172
+ "v2.2016" (the original GLODAPv2).
140
173
  gpath : str of None, optional
141
174
  Where to save the downloaded file, by default `None`, in which case the
142
175
  file is saved at "~/.glodap".
@@ -146,24 +179,29 @@ def download(region="world", version=None, gpath=None, chunk_size=8192):
146
179
  gpath, fileregion, filename, version = _get_paths(region, version, gpath)
147
180
  if not os.path.isdir(gpath):
148
181
  os.makedirs(gpath)
149
- url = (
150
- f"https://glodap.info/glodap_files/{version}/"
151
- + f"GLODAP{version}_{fileregion}.mat"
152
- )
153
- hasher = hashlib.new("sha256")
182
+ if version == "v2.2016":
183
+ fr = fileregion.replace("_", " ")
184
+ url = (
185
+ f"https://glodap.info/glodap_files/{version}/"
186
+ + f"GLODAPv2 {fr}.mat"
187
+ )
188
+ elif version.startswith("v2"):
189
+ url = (
190
+ f"https://glodap.info/glodap_files/{version}/"
191
+ + f"GLODAP{version}_{fileregion}.mat"
192
+ )
193
+ elif version.startswith("v3"):
194
+ url = (
195
+ "https://glodap.info/glodap_files/v3/"
196
+ + f"GLODAPv3_{fileregion}.csv.zip"
197
+ )
154
198
  checksum = checksums[version][region[:3].lower()]
155
- with tempfile.TemporaryDirectory() as tdir:
156
- temp_path = os.path.join(tdir, filename)
157
- with requests.get(url, stream=True) as r:
158
- r.raise_for_status()
159
- with open(temp_path, "wb") as f:
160
- for chunk in r.iter_content(chunk_size=chunk_size):
161
- f.write(chunk)
162
- hasher.update(chunk)
163
- if hasher.hexdigest() == checksum:
164
- os.rename(temp_path, os.path.join(gpath, filename))
165
- else:
166
- warn("File checksum not as expected - download failed.")
199
+ pooch.retrieve(
200
+ url,
201
+ known_hash=f"sha256:{checksum}",
202
+ fname=filename,
203
+ path=gpath,
204
+ )
167
205
 
168
206
 
169
207
  def read(region="world", version=None, gpath=None):
@@ -183,7 +221,13 @@ def read(region="world", version=None, gpath=None):
183
221
  version : str or None, optional
184
222
  Which GLODAP version to import, by default `None`, in which case the
185
223
  most recent version is imported. The options are:
186
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
224
+ "v3.2026" (the original GLODAPv3)
225
+ "v2.2023",
226
+ "v2.2022",
227
+ "v2.2021",
228
+ "v2.2020",
229
+ "v2.2019",
230
+ "v2.2016" (the original GLODAPv2).
187
231
  gpath : str of None, optional
188
232
  Where to the downloaded file is or should be saved, by default `None`,
189
233
  in which case the file is imported from or saved at "~/.glodap".
@@ -193,19 +237,30 @@ def read(region="world", version=None, gpath=None):
193
237
  pd.DataFrame
194
238
  The GLODAP dataset as a pandas DataFrame.
195
239
  """
240
+ if region.lower() in regions_short_to_long:
241
+ region = regions_short_to_long[region.lower()]
196
242
  gpath, _, filename, version = _get_paths(region, version, gpath)
197
- try:
198
- df = loadmat(os.path.join(gpath, filename))
199
- except FileNotFoundError:
200
- download(region=region, version=version, gpath=gpath)
201
- df = loadmat(os.path.join(gpath, filename))
202
- df = pd.DataFrame(
203
- {
204
- k[2:]: [w[0][0] for w in v] if v.dtype == "O" else v.ravel()
205
- for k, v in df.items()
206
- if k.startswith("G2")
207
- }
208
- )
243
+ download(region=region, version=version, gpath=gpath)
244
+ if version.startswith("v2"):
245
+ df = loadmat(Path(gpath, filename))
246
+ df = pd.DataFrame(
247
+ {
248
+ k[2:]: [w[0][0] for w in v] if v.dtype == "O" else v.ravel()
249
+ for k, v in df.items()
250
+ if k.startswith("G2")
251
+ }
252
+ )
253
+ elif version.startswith("v3"):
254
+ with tempfile.TemporaryDirectory() as tdir:
255
+ shutil.unpack_archive(Path(gpath, filename), tdir)
256
+ tfilename = [f for f in os.listdir(tdir) if f.endswith(".csv")][0]
257
+ df = pd.read_csv(
258
+ Path(tdir, tfilename),
259
+ dtype={
260
+ "expocode": str,
261
+ "ph_scale": str,
262
+ },
263
+ ).replace([-9999, "-9999"], np.nan)
209
264
  # Convert columns that should be integers into integers
210
265
  # Can't convert cast, hour, minute to integers because they have missing
211
266
  # values
@@ -251,11 +306,26 @@ def read(region="world", version=None, gpath=None):
251
306
  "tdnf",
252
307
  "chlaf",
253
308
  ]
309
+ if region in ["indian", "world"] and version == "v2.2016":
310
+ for k in keys_flags:
311
+ if k in df:
312
+ df.loc[df[k].isnull(), k] = 9
254
313
  for k in keys_integers + keys_flags:
255
- df[k] = df[k].astype(int)
314
+ if k in df:
315
+ df[k] = df[k].astype(int)
256
316
  # Rename columns for PyCO2SYS, if requested
257
317
  renamer_flags = {k: k[:-1] + "_f" for k in keys_flags}
258
318
  df = df.rename(columns=renamer_flags)
319
+ # Correct fatal datetime errors in v2.2016
320
+ if version == "v2.2016":
321
+ if region in ["indian", "world"]:
322
+ L = (df.cruise == 696) & (df.station == 15537)
323
+ df.loc[L, "month"] = 12
324
+ df.loc[L, "day"] = 1
325
+ if region in ["pacific", "world"]:
326
+ L = (df.cruise == 270) & (df.station == 113)
327
+ df.loc[L, "month"] = 4
328
+ df.loc[L, "day"] = 30
259
329
  # Calculate datetime for convenience - don't include hour and minute
260
330
  # because some are missing
261
331
  df["datetime"] = pd.to_datetime(
@@ -281,7 +351,13 @@ def arctic(version=None, gpath=None):
281
351
  version : str or None, optional
282
352
  Which GLODAP version to import, by default `None`, in which case the
283
353
  most recent version is imported. The options are:
284
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
354
+ "v3.2026" (the original GLODAPv3)
355
+ "v2.2023",
356
+ "v2.2022",
357
+ "v2.2021",
358
+ "v2.2020",
359
+ "v2.2019",
360
+ "v2.2016" (the original GLODAPv2).
285
361
  gpath : str of None, optional
286
362
  Where to the downloaded file is or should be saved, by default `None`,
287
363
  in which case the file is imported from or saved at "~/.glodap".
@@ -307,7 +383,13 @@ def atlantic(version=None, gpath=None):
307
383
  version : str or None, optional
308
384
  Which GLODAP version to import, by default `None`, in which case the
309
385
  most recent version is imported. The options are:
310
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
386
+ "v3.2026" (the original GLODAPv3)
387
+ "v2.2023",
388
+ "v2.2022",
389
+ "v2.2021",
390
+ "v2.2020",
391
+ "v2.2019",
392
+ "v2.2016" (the original GLODAPv2).
311
393
  gpath : str of None, optional
312
394
  Where to the downloaded file is or should be saved, by default `None`,
313
395
  in which case the file is imported from or saved at "~/.glodap".
@@ -333,7 +415,13 @@ def indian(version=None, gpath=None):
333
415
  version : str or None, optional
334
416
  Which GLODAP version to import, by default `None`, in which case the
335
417
  most recent version is imported. The options are:
336
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
418
+ "v3.2026" (the original GLODAPv3)
419
+ "v2.2023",
420
+ "v2.2022",
421
+ "v2.2021",
422
+ "v2.2020",
423
+ "v2.2019",
424
+ "v2.2016" (the original GLODAPv2).
337
425
  gpath : str of None, optional
338
426
  Where to the downloaded file is or should be saved, by default `None`,
339
427
  in which case the file is imported from or saved at "~/.glodap".
@@ -359,7 +447,13 @@ def pacific(version=None, gpath=None):
359
447
  version : str or None, optional
360
448
  Which GLODAP version to import, by default `None`, in which case the
361
449
  most recent version is imported. The options are:
362
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
450
+ "v3.2026" (the original GLODAPv3)
451
+ "v2.2023",
452
+ "v2.2022",
453
+ "v2.2021",
454
+ "v2.2020",
455
+ "v2.2019",
456
+ "v2.2016" (the original GLODAPv2).
363
457
  gpath : str of None, optional
364
458
  Where to the downloaded file is or should be saved, by default `None`,
365
459
  in which case the file is imported from or saved at "~/.glodap".
@@ -385,7 +479,13 @@ def world(version=None, gpath=None):
385
479
  version : str or None, optional
386
480
  Which GLODAP version to import, by default `None`, in which case the
387
481
  most recent version is imported. The options are:
388
- "v2.2023", "v2.2022", "v2.2021", "v2.2020", "v2.2019"
482
+ "v3.2026" (the original GLODAPv3)
483
+ "v2.2023",
484
+ "v2.2022",
485
+ "v2.2021",
486
+ "v2.2020",
487
+ "v2.2019",
488
+ "v2.2016" (the original GLODAPv2).
389
489
  gpath : str of None, optional
390
490
  Where to the downloaded file is or should be saved, by default `None`,
391
491
  in which case the file is imported from or saved at "~/.glodap".
@@ -8,18 +8,18 @@ build-backend = "setuptools.build_meta"
8
8
  name = "glodap"
9
9
  description = "GLODAP downloader and importer in Python"
10
10
  readme = "README.md"
11
- requires-python = ">= 3.10"
11
+ requires-python = ">= 3.11"
12
12
  dependencies = [
13
- "pandas",
14
- "requests",
15
- "scipy",
13
+ "pandas>=3.0.3,<4",
14
+ "pooch>=1.9.0,<2",
15
+ "scipy>=1.17.1,<2",
16
16
  ]
17
17
  classifiers = [
18
18
  "Development Status :: 4 - Beta",
19
- "Programming Language :: Python :: 3.10",
20
19
  "Programming Language :: Python :: 3.11",
21
20
  "Programming Language :: Python :: 3.12",
22
21
  "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
23
  "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
24
24
  "Operating System :: OS Independent",
25
25
  "Natural Language :: English",
@@ -34,3 +34,16 @@ include = ["glodap*"]
34
34
 
35
35
  [tool.setuptools.dynamic]
36
36
  version = {attr = "glodap.__version__"}
37
+
38
+ [tool.ruff]
39
+ line-length = 79
40
+
41
+ [tool.ruff.lint.isort]
42
+ combine-as-imports = true
43
+ force-single-line = false
44
+ lines-after-imports = 2
45
+
46
+ [dependency-groups]
47
+ dev = [
48
+ "ipykernel>=7.3.0",
49
+ ]
@@ -2,16 +2,18 @@
2
2
  import itertools
3
3
  import tempfile
4
4
 
5
+ import pandas as pd
6
+
5
7
  import glodap
6
8
 
7
9
 
8
- def test_response():
10
+ def test_download_and_read():
9
11
  with tempfile.TemporaryDirectory() as tdir:
10
12
  for region, version in itertools.product(
11
13
  glodap.regions, glodap.versions
12
14
  ):
13
- print(region, version)
14
- glodap.download(region=region, version=version, gpath=tdir)
15
+ df = glodap.read(region=region, version=version, gpath=tdir)
16
+ assert isinstance(df, pd.DataFrame)
15
17
 
16
18
 
17
- # test_response()
19
+ # test_download_and_read()
@@ -0,0 +1,27 @@
1
+ # %%
2
+ import pandas as pd
3
+
4
+ import glodap
5
+
6
+
7
+ def test_region_names():
8
+ # Check that the first 3 letters of each region name are unique
9
+ regions_short = {k[:3] for k in glodap.regions}
10
+ assert len(regions_short) == len(glodap.regions)
11
+
12
+
13
+ def test_regions_latest():
14
+ df = glodap.arctic()
15
+ assert isinstance(df, pd.DataFrame)
16
+ df = glodap.atlantic()
17
+ assert isinstance(df, pd.DataFrame)
18
+ df = glodap.indian()
19
+ assert isinstance(df, pd.DataFrame)
20
+ df = glodap.pacific()
21
+ assert isinstance(df, pd.DataFrame)
22
+ df = glodap.world()
23
+ assert isinstance(df, pd.DataFrame)
24
+
25
+
26
+ # test_region_names()
27
+ # test_regions_latest()
@@ -1,3 +0,0 @@
1
- pandas
2
- requests
3
- scipy
@@ -1,12 +0,0 @@
1
- # %%
2
- import pandas as pd
3
-
4
- import glodap
5
-
6
-
7
- def test_import():
8
- df = glodap.arctic(gpath="tests/data")
9
- assert isinstance(df, pd.DataFrame)
10
-
11
-
12
- # test_import()
@@ -1,11 +0,0 @@
1
- # %%
2
- import glodap
3
-
4
-
5
- def test_region_names():
6
- # Check that the first 3 letters of each region name are unique
7
- regions_short = {k[:3] for k in glodap.regions}
8
- assert len(regions_short) == len(glodap.regions)
9
-
10
-
11
- # test_region_names()
File without changes
File without changes
File without changes