hapiclient 0.2.6__tar.gz → 0.2.8__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.
Files changed (39) hide show
  1. {hapiclient-0.2.6 → hapiclient-0.2.8}/CHANGES.txt +18 -2
  2. {hapiclient-0.2.6 → hapiclient-0.2.8}/PKG-INFO +59 -7
  3. hapiclient-0.2.6/hapiclient.egg-info/PKG-INFO → hapiclient-0.2.8/README.md +43 -16
  4. {hapiclient-0.2.6 → hapiclient-0.2.8}/hapiclient/__init__.py +10 -1
  5. hapiclient-0.2.8/hapiclient/cache.py +255 -0
  6. hapiclient-0.2.8/hapiclient/capabilities.py +42 -0
  7. hapiclient-0.2.8/hapiclient/catalog.py +10 -0
  8. hapiclient-0.2.8/hapiclient/data.py +271 -0
  9. hapiclient-0.2.8/hapiclient/get.py +408 -0
  10. hapiclient-0.2.8/hapiclient/hapi.py +255 -0
  11. {hapiclient-0.2.6 → hapiclient-0.2.8}/hapiclient/hapitime.py +49 -63
  12. hapiclient-0.2.8/hapiclient/info.py +26 -0
  13. hapiclient-0.2.8/hapiclient/log.py +51 -0
  14. hapiclient-0.2.8/hapiclient/servers.py +16 -0
  15. {hapiclient-0.2.6 → hapiclient-0.2.8}/hapiclient/util.py +143 -140
  16. hapiclient-0.2.6/README.md → hapiclient-0.2.8/hapiclient.egg-info/PKG-INFO +68 -5
  17. hapiclient-0.2.8/hapiclient.egg-info/SOURCES.txt +29 -0
  18. {hapiclient-0.2.6 → hapiclient-0.2.8}/setup.py +6 -3
  19. {hapiclient-0.2.6/hapiclient → hapiclient-0.2.8}/test/test_chunking.py +86 -58
  20. hapiclient-0.2.8/test/test_datetime2hapitime.py +32 -0
  21. hapiclient-0.2.8/test/test_hapi_data_requests.py +224 -0
  22. hapiclient-0.2.8/test/test_hapi_metadata_requests.py +152 -0
  23. hapiclient-0.2.8/test/test_hapitime2datetime.py +102 -0
  24. hapiclient-0.2.8/test/test_hapitime_reformat.py +83 -0
  25. hapiclient-0.2.8/test/test_logging.py +137 -0
  26. hapiclient-0.2.6/hapiclient/hapi.py +0 -1060
  27. hapiclient-0.2.6/hapiclient/test/__init__.py +0 -0
  28. hapiclient-0.2.6/hapiclient/test/compare.py +0 -240
  29. hapiclient-0.2.6/hapiclient/test/test_datetime2hapitime.py +0 -17
  30. hapiclient-0.2.6/hapiclient/test/test_hapi.py +0 -340
  31. hapiclient-0.2.6/hapiclient/test/test_hapitime2datetime.py +0 -124
  32. hapiclient-0.2.6/hapiclient/test/test_hapitime_reformat.py +0 -79
  33. hapiclient-0.2.6/hapiclient.egg-info/SOURCES.txt +0 -21
  34. {hapiclient-0.2.6 → hapiclient-0.2.8}/LICENSE.txt +0 -0
  35. {hapiclient-0.2.6 → hapiclient-0.2.8}/MANIFEST.in +0 -0
  36. {hapiclient-0.2.6 → hapiclient-0.2.8}/hapiclient.egg-info/dependency_links.txt +0 -0
  37. {hapiclient-0.2.6 → hapiclient-0.2.8}/hapiclient.egg-info/requires.txt +1 -1
  38. {hapiclient-0.2.6 → hapiclient-0.2.8}/hapiclient.egg-info/top_level.txt +0 -0
  39. {hapiclient-0.2.6 → hapiclient-0.2.8}/setup.cfg +0 -0
@@ -10,7 +10,7 @@ v0.0.6:
10
10
  2018-10-04 -- Improve dateticks.py
11
11
  2018-10-04 -- Add hapi_demo.ipynb
12
12
  2018-10-04 -- Other documentation improvements
13
- v0.0.7:
13
+ v0.0.7:
14
14
  2018-10-06 -- Improve documentation
15
15
  2018-10-06 -- Add reader tests
16
16
  2018-10-23 -- Improve dateticks and tests
@@ -103,4 +103,20 @@ v0.2.6b1:
103
103
  2023-02-04 -- 2ef7cff Unicode fix; Log string fix
104
104
  2024-05-11 -- fba4ad3 Testing Updates
105
105
  v0.2.6:
106
-
106
+ 2023-05-24 -- Use token for PyPi in Makefile
107
+ v0.2.7b1:
108
+ 2025-03-01 -- Unrecognized ISO 8601 time format: '00:00:00.Z' https://github.com/hapi-server/client-python/issues/76
109
+ 2025-03-01 -- 'infer_datetime_format' is deprecated ... https://github.com/hapi-server/client-python/issues/78
110
+ 2026-04-08 -- Improve NaN handling https://github.com/hapi-server/client-python/issues/88
111
+ 2026-05-02 -- Logging and testing https://github.com/hapi-server/client-python/issues/89
112
+ v0.2.7:
113
+ 2026-05-02 -- Support for Python 2.7 dropped. This is last release with support for 3.5 through 3.8.
114
+ v0.2.8b0:
115
+ 2026-05-02 -- Documentation
116
+ v0.2.8b1:
117
+ 2026-05-02 -- Versioning updates
118
+ 2026-05-19 -- Better response error messages
119
+ v0.2.8b2:
120
+ 2026-05-20 -- Refactor
121
+ v0.2.8:
122
+ 2026-06-04 -- Compat. fixes for hapiplot package.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: hapiclient
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Interface to Heliophysics data server API
5
5
  Home-page: http://pypi.python.org/pypi/hapiclient/
6
6
  Author: Bob Weigel
@@ -8,13 +8,29 @@ Author-email: rweigel@gmu.edu
8
8
  License: LICENSE.txt
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE.txt
11
+ Requires-Dist: urllib3
12
+ Requires-Dist: joblib
13
+ Requires-Dist: isodate>=0.6.0
14
+ Requires-Dist: pandas>=0.23
15
+ Requires-Dist: numpy>=1.14.3
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: description
19
+ Dynamic: description-content-type
20
+ Dynamic: home-page
21
+ Dynamic: license
22
+ Dynamic: license-file
23
+ Dynamic: requires-dist
24
+ Dynamic: summary
11
25
 
12
26
  [![DOI](https://zenodo.org/badge/93170857.svg)](https://zenodo.org/badge/latestdoi/93170857)
13
27
  [![Build Status](https://app.travis-ci.com/hapi-server/client-python.svg?branch=master)](https://app.travis-ci.com/hapi-server/client-python)
14
28
 
15
29
  **HAPI Client for Python**
16
30
 
17
- Basic usage examples for various HAPI servers are given in [hapi_demo.py](https://github.com/hapi-server/client-python/blob/master/hapi_demo.py) and the Examples section of a Jupyter Notebook hosted on Google Colab: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/hapi-server/client-python-notebooks/blob/master/hapi_demo.ipynb#examples).
31
+ Basic usage examples for various HAPI servers are given in [hapi_demo.py](https://github.com/hapi-server/client-python/blob/master/hapi_demo.py). See also
32
+ * Examples section of a Jupyter Notebook hosted on Google Colab: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/hapi-server/client-python-notebooks/blob/master/hapi_demo.ipynb#examples).
33
+ * [PyHC Summer School tutorials](https://github.com/hapi-server/tutorial-python)
18
34
 
19
35
  # Installation
20
36
 
@@ -50,6 +66,7 @@ start = '2003-09-01T00:00:00'
50
66
  stop = '2003-12-01T00:00:00'
51
67
  parameters = 'DST1800'
52
68
  opts = {'logging': True}
69
+ # See misc/hapi_logging_demo.py for example of using conventional Python logging.
53
70
 
54
71
  # Get data
55
72
  data, meta = hapi(server, dataset, parameters, start, stop, **opts)
@@ -92,7 +109,41 @@ returns the [Numpy N-D array](https://docs.scipy.org/doc/numpy-1.15.1/user/quick
92
109
 
93
110
  The HAPI client data model is intentionally basic. There is an ongoing discussion of a data model for Heliophysics data among the [PyHC community](https://heliopython.org/). When this data model is complete, a function that converts `data` and `meta` to that data model will be included in the `hapiclient` package.
94
111
 
95
- # Development
112
+ # Development and Testing
113
+
114
+ ## Testing Python versions available with tox-env
115
+
116
+ As of 2026-04-14, Python 3.8+ is available with tox-env.
117
+
118
+ ```bash
119
+ git clone https://github.com/hapi-server/client-python
120
+ cd client-python; python -m pip install -e .
121
+
122
+ # Run a specific test on current Python version (default is log_level=INFO
123
+ # for hapiclient logger and test logger when executed this way).
124
+ python test/test_hapi_data_requests.py
125
+
126
+ # Run a specific test on a specific Python version with all logging
127
+ tox -e py311 -- test/test_hapi_data_requests.py
128
+ # Set log level for test logger
129
+ tox -e py311 -- test/test_hapi_data_requests.py --log-level=INFO
130
+
131
+ # Run a specific test on all Python versions set by tox.ini `envlist`
132
+ tox -- test/test_hapi_data_requests.py
133
+
134
+ # Run all tests in ./test
135
+ tox
136
+
137
+ # Run long-running tests
138
+ tox -e long-test
139
+
140
+ # Run long-running tests on a specific Python version
141
+ tox -e long-test --override testenv:long-test.basepython=python3.11
142
+ ```
143
+
144
+ ## Testing Python versions available with Anaconda
145
+
146
+ As of 2026-04-14, Python 3.5+ is available with Anaconda.
96
147
 
97
148
  ```bash
98
149
  git clone https://github.com/hapi-server/client-python
@@ -117,12 +168,13 @@ make repository-test
117
168
 
118
169
  To run an individual unit test in a Python session, use, e.g.,
119
170
 
120
- ```python
121
- from hapiclient.test.test_hapi import test_reader_short
122
- test_reader_short()
171
+ ```bash
172
+ cd test; python test_hapitime_reformat.py
123
173
  ```
124
174
 
125
175
  # Contact
126
176
 
127
177
  Submit bug reports and feature requests on the [repository issue
128
178
  tracker](https://github.com/hapi-server/client-python/issues>).
179
+
180
+ Before submitting a pull request, please post an issue with the proposed changes for discussion prior to developing the pull request.
@@ -1,20 +1,11 @@
1
- Metadata-Version: 2.1
2
- Name: hapiclient
3
- Version: 0.2.6
4
- Summary: Interface to Heliophysics data server API
5
- Home-page: http://pypi.python.org/pypi/hapiclient/
6
- Author: Bob Weigel
7
- Author-email: rweigel@gmu.edu
8
- License: LICENSE.txt
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE.txt
11
-
12
1
  [![DOI](https://zenodo.org/badge/93170857.svg)](https://zenodo.org/badge/latestdoi/93170857)
13
2
  [![Build Status](https://app.travis-ci.com/hapi-server/client-python.svg?branch=master)](https://app.travis-ci.com/hapi-server/client-python)
14
3
 
15
4
  **HAPI Client for Python**
16
5
 
17
- Basic usage examples for various HAPI servers are given in [hapi_demo.py](https://github.com/hapi-server/client-python/blob/master/hapi_demo.py) and the Examples section of a Jupyter Notebook hosted on Google Colab: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/hapi-server/client-python-notebooks/blob/master/hapi_demo.ipynb#examples).
6
+ Basic usage examples for various HAPI servers are given in [hapi_demo.py](https://github.com/hapi-server/client-python/blob/master/hapi_demo.py). See also
7
+ * Examples section of a Jupyter Notebook hosted on Google Colab: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/hapi-server/client-python-notebooks/blob/master/hapi_demo.ipynb#examples).
8
+ * [PyHC Summer School tutorials](https://github.com/hapi-server/tutorial-python)
18
9
 
19
10
  # Installation
20
11
 
@@ -50,6 +41,7 @@ start = '2003-09-01T00:00:00'
50
41
  stop = '2003-12-01T00:00:00'
51
42
  parameters = 'DST1800'
52
43
  opts = {'logging': True}
44
+ # See misc/hapi_logging_demo.py for example of using conventional Python logging.
53
45
 
54
46
  # Get data
55
47
  data, meta = hapi(server, dataset, parameters, start, stop, **opts)
@@ -92,7 +84,41 @@ returns the [Numpy N-D array](https://docs.scipy.org/doc/numpy-1.15.1/user/quick
92
84
 
93
85
  The HAPI client data model is intentionally basic. There is an ongoing discussion of a data model for Heliophysics data among the [PyHC community](https://heliopython.org/). When this data model is complete, a function that converts `data` and `meta` to that data model will be included in the `hapiclient` package.
94
86
 
95
- # Development
87
+ # Development and Testing
88
+
89
+ ## Testing Python versions available with tox-env
90
+
91
+ As of 2026-04-14, Python 3.8+ is available with tox-env.
92
+
93
+ ```bash
94
+ git clone https://github.com/hapi-server/client-python
95
+ cd client-python; python -m pip install -e .
96
+
97
+ # Run a specific test on current Python version (default is log_level=INFO
98
+ # for hapiclient logger and test logger when executed this way).
99
+ python test/test_hapi_data_requests.py
100
+
101
+ # Run a specific test on a specific Python version with all logging
102
+ tox -e py311 -- test/test_hapi_data_requests.py
103
+ # Set log level for test logger
104
+ tox -e py311 -- test/test_hapi_data_requests.py --log-level=INFO
105
+
106
+ # Run a specific test on all Python versions set by tox.ini `envlist`
107
+ tox -- test/test_hapi_data_requests.py
108
+
109
+ # Run all tests in ./test
110
+ tox
111
+
112
+ # Run long-running tests
113
+ tox -e long-test
114
+
115
+ # Run long-running tests on a specific Python version
116
+ tox -e long-test --override testenv:long-test.basepython=python3.11
117
+ ```
118
+
119
+ ## Testing Python versions available with Anaconda
120
+
121
+ As of 2026-04-14, Python 3.5+ is available with Anaconda.
96
122
 
97
123
  ```bash
98
124
  git clone https://github.com/hapi-server/client-python
@@ -117,12 +143,13 @@ make repository-test
117
143
 
118
144
  To run an individual unit test in a Python session, use, e.g.,
119
145
 
120
- ```python
121
- from hapiclient.test.test_hapi import test_reader_short
122
- test_reader_short()
146
+ ```bash
147
+ cd test; python test_hapitime_reformat.py
123
148
  ```
124
149
 
125
150
  # Contact
126
151
 
127
152
  Submit bug reports and feature requests on the [repository issue
128
153
  tracker](https://github.com/hapi-server/client-python/issues>).
154
+
155
+ Before submitting a pull request, please post an issue with the proposed changes for discussion prior to developing the pull request.
@@ -1,6 +1,9 @@
1
1
  # Allow "from hapiclient import hapi"
2
2
  from hapiclient.hapi import hapi
3
3
 
4
+ # Allow "from hapiclient import request2path"
5
+ from hapiclient.hapi import request2path
6
+
4
7
  # Allow "from hapiclient import hapitime2datetime"
5
8
  from hapiclient.hapitime import hapitime2datetime
6
9
 
@@ -10,9 +13,15 @@ from hapiclient.hapitime import datetime2hapitime
10
13
  # Allow "from hapiclient import HAPIError"
11
14
  from hapiclient.util import HAPIError
12
15
 
13
- __version__ = '0.2.6'
16
+ __version__ = '0.2.8'
14
17
 
15
18
  import sys
19
+ import platform
20
+
21
+ if sys.version_info < (3, 10) and platform.system() == "Darwin":
22
+ import warnings
23
+ warnings.filterwarnings("ignore", message=".*urllib3.*OpenSSL.*")
24
+
16
25
  if sys.version_info[0] < 3:
17
26
  # Python 2.7
18
27
  reload(sys)
@@ -0,0 +1,255 @@
1
+ def server2dirname(server):
2
+ """Convert a server URL to a directory name."""
3
+
4
+ import re
5
+
6
+ urld = re.sub(r"https*://", "", server)
7
+ urld = re.sub(r'/', '_', urld)
8
+
9
+ return urld
10
+
11
+
12
+ def cachedir(*args):
13
+ """HAPI cache directory.
14
+
15
+ cachedir() returns os.path.join(tempfile.gettempdir(), 'hapi-data')
16
+
17
+ cachedir(basedir, server) returns os.path.join(basedir, server2dirname(server))
18
+ """
19
+
20
+ import os
21
+ import tempfile
22
+
23
+ if len(args) != 0 and len(args) != 2:
24
+ raise ValueError('cachedir() takes either 0 or 2 arguments.')
25
+
26
+ if len(args) == 0:
27
+ # cachedir()
28
+ return os.path.join(tempfile.gettempdir(), 'hapi-data')
29
+
30
+ if len(args) == 2:
31
+ # cachedir(base_dir, server)
32
+ return os.path.join(args[0], server2dirname(args[1]))
33
+
34
+
35
+ def request2path(*args):
36
+ # request2path(server, dataset, parameters, start, stop)
37
+ # request2path(server, dataset, parameters, start, stop, cachedir)
38
+ import os
39
+ import re
40
+ import platform
41
+
42
+ if len(args) == 5:
43
+ # Use default if cachedir not given.
44
+ cachedirectory = cachedir()
45
+ else:
46
+ cachedirectory = args[5]
47
+
48
+ args = list(args)
49
+
50
+ # Replace forbidden characters in directory and filename
51
+ # Replacements assume that there will be no name collisions,
52
+ # e.g., one parameter named abc-< and another abc-@lt@.
53
+ # This also introduces an incompatibility between caches on Windows
54
+ # Unix.
55
+ if platform.system() == 'Windows':
56
+ # List and code from responses in
57
+ # https://stackoverflow.com/q/1976007
58
+ reps = (
59
+ ('<', '@lt@'),
60
+ ('>', '@gt@'),
61
+ (':', '@colon@'),
62
+ ('"', '@doublequote@'),
63
+ ('/', '@forwardslash@'),
64
+ ('/', '@backslash@'),
65
+ ('\\|', '@pipe@'),
66
+ ('\\?', '@questionmark@'),
67
+ ('\\*', '@asterisk@')
68
+ )
69
+
70
+ for element in reps:
71
+ args[1] = re.sub(element[0], element[1], args[1])
72
+ args[2] = re.sub(element[0], element[1], args[2])
73
+
74
+ else:
75
+ args[1] = re.sub('/','@forwardslash@',args[1])
76
+ args[2] = re.sub('/','@forwardslash@',args[2])
77
+
78
+ # To shorten filenames.
79
+ args[3] = re.sub(r'-|:|\.|Z', '', args[3])
80
+ args[4] = re.sub(r'-|:|\.|Z', '', args[4])
81
+
82
+ # URL subdirectory
83
+ urldirectory = server2dirname(args[0])
84
+ fname = '%s_%s_%s_%s' % (args[1], args[2], args[3], args[4])
85
+
86
+ return os.path.join(cachedirectory, urldirectory, fname)
87
+
88
+
89
+ def meta_cache_paths(SERVER, DATASET, cachedir):
90
+ """Return dict with metadata cache directory and file names."""
91
+
92
+ fname_root = request2path(SERVER, DATASET, '', '', '', cachedir)
93
+
94
+ return {
95
+ 'json': fname_root + '.json',
96
+ 'pkl': fname_root + '.pkl'
97
+ }
98
+
99
+
100
+ def meta_cache_read(SERVER, DATASET, opts):
101
+ """Read metadata from PKL cache. Returns meta dict or None."""
102
+
103
+ import os
104
+ import pickle
105
+
106
+ from hapiclient.log import log
107
+
108
+ if not opts["usecache"]:
109
+ log('Not checking metadata cache because usecache is False.')
110
+ return None
111
+
112
+ fnamepkl = meta_cache_paths(SERVER, DATASET, opts['cachedir'])['pkl']
113
+ if os.path.isfile(fnamepkl):
114
+ log('Reading %s' % os.path.basename(fnamepkl))
115
+ with open(fnamepkl, 'rb') as f:
116
+ return pickle.load(f)
117
+
118
+ if opts["usecache"]:
119
+ log('No metadata cache file found: %s' % os.path.basename(fnamepkl))
120
+
121
+ return None
122
+
123
+
124
+ def meta_cache_write(meta, SERVER, DATASET, opts):
125
+ """Write metadata to JSON and PKL cache files."""
126
+
127
+ import os
128
+ import json
129
+ import pickle
130
+
131
+ from hapiclient.log import log
132
+
133
+ if not opts["cache"]:
134
+ return
135
+
136
+ paths = meta_cache_paths(SERVER, DATASET, opts['cachedir'])
137
+ fnamejson, fnamepkl = paths['json'], paths['pkl']
138
+
139
+ server_dir = cachedir(opts["cachedir"], SERVER)
140
+ os.makedirs(server_dir, exist_ok=True)
141
+
142
+ log('Writing %s ' % os.path.basename(fnamejson))
143
+ with open(fnamejson, 'w') as f:
144
+ json.dump(meta, f, indent=4)
145
+
146
+ log('Writing %s ' % os.path.basename(fnamepkl))
147
+ with open(fnamepkl, 'wb') as f:
148
+ # protocol=2 used for Python 2.7 compatibility.
149
+ pickle.dump(meta, f, protocol=2)
150
+
151
+
152
+ def data_cache_paths(SERVER, DATASET, PARAMETERS, START, STOP, cachedir):
153
+ """Return dict with data cache file names."""
154
+
155
+ fname_root = request2path(SERVER, DATASET, PARAMETERS, START, STOP, cachedir)
156
+
157
+ return {
158
+ 'csv': fname_root + '.csv',
159
+ 'bin': fname_root + '.bin',
160
+ 'npy': fname_root + '.npy',
161
+ 'pkl': fname_root + '.pkl'
162
+ }
163
+
164
+
165
+ def data_cache_read_metax(SERVER, DATASET, PARAMETERS, START, STOP, opts):
166
+ """Read extended request metadata from PKL cache. Returns meta dict or None."""
167
+
168
+ import os
169
+ import pickle
170
+
171
+ from hapiclient.log import log
172
+
173
+ if not opts["usecache"]:
174
+ log('Not checking data cache because usecache is False.')
175
+ return None
176
+
177
+ fnamepklx = data_cache_paths(SERVER, DATASET, PARAMETERS, START, STOP, opts['cachedir'])['pkl']
178
+ if os.path.isfile(fnamepklx):
179
+ log('Reading subsetted metadata cache %s' % os.path.basename(fnamepklx))
180
+ with open(fnamepklx, 'rb') as f:
181
+ return pickle.load(f)
182
+ if opts["usecache"]:
183
+ log('No subsetted metadata cache file found: %s' % os.path.basename(fnamepklx))
184
+
185
+ return None
186
+
187
+
188
+ def data_cache_read_npy(SERVER, DATASET, PARAMETERS, START, STOP, opts):
189
+ """Read cached numpy data array. Returns None if not cached."""
190
+
191
+ import os
192
+ import numpy as np
193
+
194
+ from hapiclient.log import log
195
+
196
+ if not opts["usecache"]:
197
+ return None
198
+
199
+ fnamenpy = data_cache_paths(SERVER, DATASET, PARAMETERS, START, STOP, opts['cachedir'])['npy']
200
+
201
+ if not os.path.isfile(fnamenpy):
202
+ return None
203
+
204
+ log('Reading %s ' % os.path.basename(fnamenpy))
205
+ with open(fnamenpy, 'rb') as f:
206
+ data = np.load(f)
207
+
208
+ return data
209
+
210
+
211
+ def data_cache_write(data_result, meta, SERVER, DATASET, PARAMETERS, START, STOP, opts):
212
+ """Write data array and extended metadata to cache files.
213
+
214
+ Also updates meta with file-related x_ fields before writing.
215
+ """
216
+
217
+ import os
218
+ import pickle
219
+ import warnings
220
+ import numpy as np
221
+
222
+ from hapiclient.log import log
223
+
224
+ data_paths = data_cache_paths(SERVER, DATASET, PARAMETERS, START, STOP, opts['cachedir'])
225
+ fnamecsv, fnamebin, fnamenpy, fnamepklx = data_paths['csv'], data_paths['bin'], data_paths['npy'], data_paths['pkl']
226
+
227
+ meta_paths = meta_cache_paths(SERVER, DATASET, opts['cachedir'])
228
+ fnamejson, fnamepkl = meta_paths['json'], meta_paths['pkl']
229
+
230
+ meta.update({"x_metaFileParsed": fnamepkl})
231
+ meta.update({"x_dataFileParsed": fnamenpy})
232
+ meta.update({"x_metaFile": fnamejson})
233
+ meta.update({"x_dataFile": fnamebin if opts['format'] == 'binary' else fnamecsv})
234
+
235
+ if not opts["cache"]:
236
+ # Need to return after meta is updated.
237
+ return
238
+
239
+ server_dir = cachedir(opts["cachedir"], SERVER)
240
+ os.makedirs(server_dir, exist_ok=True)
241
+
242
+ log('Writing %s' % os.path.basename(fnamepklx))
243
+ with open(fnamepklx, 'wb') as f:
244
+ pickle.dump(meta, f, protocol=2)
245
+
246
+ log('Writing %s' % os.path.basename(fnamenpy))
247
+ with warnings.catch_warnings():
248
+ # Ignore warning that occurs when saving Unicode data.
249
+ kwargs = {
250
+ 'message': r"Stored array in format 3\.0.*",
251
+ 'category': UserWarning,
252
+ 'module': r"numpy\.lib\.format"
253
+ }
254
+ warnings.filterwarnings("ignore", **kwargs)
255
+ np.save(fnamenpy, data_result)
@@ -0,0 +1,42 @@
1
+
2
+ def capabilities(SERVER):
3
+ """Return the capabilities of a HAPI server.
4
+
5
+ Args:
6
+ SERVER (str): The base URL of the HAPI server.
7
+
8
+ Returns:
9
+ dict: A dictionary containing the capabilities of the server.
10
+ """
11
+ from hapiclient.util import urlopen
12
+
13
+ caps = urlopen(SERVER + '/capabilities', parse_json=True)
14
+
15
+ return caps
16
+
17
+
18
+ def get_format(SERVER, format):
19
+ """Return the transport format to use, accounting for server capabilities.
20
+
21
+ If the requested format is not supported by the server, falls back to 'csv'
22
+ with a warning.
23
+ """
24
+
25
+ from hapiclient.util import error, warning
26
+
27
+ cformats = ['csv', 'binary'] # client formats
28
+ if format not in cformats:
29
+ msg = 'This client does not handle transport format "%s". Available options: %s'
30
+ error(msg % (format, ', '.join(cformats)))
31
+
32
+ if format != 'csv':
33
+ caps = capabilities(SERVER)
34
+ sformats = caps["outputFormats"] # Server formats
35
+ if format not in sformats:
36
+ msg = 'Requested transport format "%s" not avaiable from %s. Will use "csv". Available options: %s'
37
+ warning(msg % (format, SERVER, ', '.join(sformats)))
38
+ format = 'csv'
39
+ if 'binary' not in sformats:
40
+ format = 'csv'
41
+
42
+ return format
@@ -0,0 +1,10 @@
1
+ from hapiclient.log import log
2
+ from hapiclient.util import urlopen
3
+
4
+
5
+ def catalog(SERVER):
6
+ # TODO: Cache
7
+ url = SERVER + '/catalog'
8
+ meta = urlopen(url, parse_json=True)
9
+
10
+ return meta