cdasws 1.7.47__tar.gz → 1.8.3__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.
- {cdasws-1.7.47 → cdasws-1.8.3}/PKG-INFO +2 -2
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws/__init__.py +461 -107
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws/datarequest.py +4 -2
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws/timeinterval.py +21 -6
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws.egg-info/PKG-INFO +2 -2
- {cdasws-1.7.47 → cdasws-1.8.3}/setup.py +2 -1
- {cdasws-1.7.47 → cdasws-1.8.3}/README.md +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws/__main__.py +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws/datarepresentation.py +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws.egg-info/SOURCES.txt +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws.egg-info/dependency_links.txt +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws.egg-info/requires.txt +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/cdasws.egg-info/top_level.txt +0 -0
- {cdasws-1.7.47 → cdasws-1.8.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cdasws
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.3
|
|
4
4
|
Summary: NASA's Coordinated Data Analysis System Web Service Client Library
|
|
5
5
|
Home-page: https://cdaweb.gsfc.nasa.gov/WebServices/REST
|
|
6
6
|
Author: Bernie Harris
|
|
@@ -125,5 +125,5 @@ Classifier: Programming Language :: Python
|
|
|
125
125
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
126
126
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
127
127
|
Description-Content-Type: text/markdown
|
|
128
|
-
Provides-Extra: xarray
|
|
129
128
|
Provides-Extra: spdm
|
|
129
|
+
Provides-Extra: xarray
|
|
@@ -41,10 +41,17 @@ the United States under Title 17, U.S.Code. All Other Rights Reserved.
|
|
|
41
41
|
|
|
42
42
|
Notes
|
|
43
43
|
-----
|
|
44
|
-
|
|
45
|
-
to
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
<ul>
|
|
45
|
+
<li>Due to rate limiting implemented by the CDAS web services, an
|
|
46
|
+
attempt to make simultaneous requests from many threads is likely
|
|
47
|
+
to actually reduce performance. At this time, it is best to make
|
|
48
|
+
calls from five or fewer threads.</li>
|
|
49
|
+
<li>Since CDAS data has datetime values with a UTC timezone, all
|
|
50
|
+
client provided datetime values should have a timezone of UTC.
|
|
51
|
+
If a given value's timezone is not UTC, the value is adjusted to
|
|
52
|
+
UTC. If a given value has no timezone (is naive), a UTC timezone
|
|
53
|
+
is set.</li>
|
|
54
|
+
</ul>
|
|
48
55
|
"""
|
|
49
56
|
|
|
50
57
|
|
|
@@ -53,12 +60,14 @@ import os
|
|
|
53
60
|
import platform
|
|
54
61
|
import logging
|
|
55
62
|
import re
|
|
63
|
+
from importlib.util import find_spec
|
|
56
64
|
import urllib.parse
|
|
57
65
|
from urllib.parse import urlparse
|
|
58
66
|
import json
|
|
59
67
|
from operator import itemgetter
|
|
60
68
|
import time
|
|
61
69
|
from datetime import datetime, timedelta, timezone
|
|
70
|
+
import xml.etree.ElementTree as ET
|
|
62
71
|
from tempfile import mkstemp
|
|
63
72
|
from typing import Any, Callable, Dict, List, Tuple, Union
|
|
64
73
|
|
|
@@ -72,11 +81,19 @@ from cdasws.datarequest import ImageFormat, GraphOptions, GraphRequest
|
|
|
72
81
|
from cdasws.datarequest import TextFormat, TextRequest, ThumbnailRequest
|
|
73
82
|
from cdasws.timeinterval import TimeInterval
|
|
74
83
|
|
|
75
|
-
|
|
84
|
+
|
|
85
|
+
# requires python >= 3.4
|
|
86
|
+
if find_spec('spacepy.datamodel') is not None:
|
|
76
87
|
import spacepy.datamodel as spdm # type: ignore
|
|
77
88
|
SPDM_AVAILABLE = True
|
|
78
|
-
|
|
89
|
+
else:
|
|
79
90
|
SPDM_AVAILABLE = False
|
|
91
|
+
# python < 3.4
|
|
92
|
+
#try:
|
|
93
|
+
# import spacepy.datamodel as spdm # type: ignore
|
|
94
|
+
# SPDM_AVAILABLE = True
|
|
95
|
+
#except ImportError:
|
|
96
|
+
# SPDM_AVAILABLE = False
|
|
80
97
|
|
|
81
98
|
try:
|
|
82
99
|
from cdflib.xarray import cdf_to_xarray
|
|
@@ -120,7 +137,7 @@ except ImportError:
|
|
|
120
137
|
CDF_XARRAY_AVAILABLE = False
|
|
121
138
|
|
|
122
139
|
|
|
123
|
-
__version__ = "1.
|
|
140
|
+
__version__ = "1.8.3"
|
|
124
141
|
|
|
125
142
|
|
|
126
143
|
#
|
|
@@ -129,6 +146,22 @@ __version__ = "1.7.47"
|
|
|
129
146
|
#
|
|
130
147
|
RETRY_LIMIT = 100
|
|
131
148
|
|
|
149
|
+
#
|
|
150
|
+
# XML schema namespace
|
|
151
|
+
#
|
|
152
|
+
NS = 'http://cdaweb.gsfc.nasa.gov/schema'
|
|
153
|
+
#
|
|
154
|
+
# XHTML schema namespace
|
|
155
|
+
#
|
|
156
|
+
XHTML_NS = 'http://www.w3.org/1999/xhtml'
|
|
157
|
+
#
|
|
158
|
+
# All namespaces found in responses.
|
|
159
|
+
#
|
|
160
|
+
NAMESPACES = {
|
|
161
|
+
'cdas': NS,
|
|
162
|
+
'xhtml': XHTML_NS
|
|
163
|
+
}
|
|
164
|
+
|
|
132
165
|
|
|
133
166
|
def _get_data_progress(
|
|
134
167
|
progress: float,
|
|
@@ -250,7 +283,7 @@ class CdasWs:
|
|
|
250
283
|
|
|
251
284
|
self._request_headers = {
|
|
252
285
|
'Content-Type' : 'application/json',
|
|
253
|
-
'Accept' : 'application/
|
|
286
|
+
'Accept' : 'application/xml',
|
|
254
287
|
'User-Agent' : self._user_agent,
|
|
255
288
|
#'Accept-Encoding' : 'gzip' # only beneficial for icdfml responses
|
|
256
289
|
}
|
|
@@ -332,17 +365,28 @@ class CdasWs:
|
|
|
332
365
|
self.logger.info('response.text: %s', response.text)
|
|
333
366
|
return []
|
|
334
367
|
|
|
335
|
-
observatory_groups = response.json()
|
|
336
|
-
|
|
337
368
|
if self.logger.level <= logging.DEBUG:
|
|
338
|
-
self.logger.debug('
|
|
339
|
-
json.dumps(observatory_groups,
|
|
340
|
-
indent=4, sort_keys=True))
|
|
369
|
+
self.logger.debug('response.text = %s', response.text)
|
|
341
370
|
|
|
342
|
-
|
|
343
|
-
|
|
371
|
+
observatory_response = ET.fromstring(response.text)
|
|
372
|
+
|
|
373
|
+
observatory_group_descriptions = []
|
|
374
|
+
for description in observatory_response.findall(\
|
|
375
|
+
'cdas:ObservatoryGroupDescription', namespaces=NAMESPACES):
|
|
376
|
+
|
|
377
|
+
observatory_ids = []
|
|
378
|
+
for observatory_id in description.findall(\
|
|
379
|
+
'cdas:ObservatoryId', namespaces=NAMESPACES):
|
|
380
|
+
|
|
381
|
+
observatory_ids.append(observatory_id.text)
|
|
344
382
|
|
|
345
|
-
|
|
383
|
+
observatory_group_descriptions.append({
|
|
384
|
+
'Name': description.find(\
|
|
385
|
+
'cdas:Name', namespaces=NAMESPACES).text,
|
|
386
|
+
'ObservatoryId': observatory_ids
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
return observatory_group_descriptions
|
|
346
390
|
|
|
347
391
|
|
|
348
392
|
def get_instrument_types(
|
|
@@ -392,17 +436,24 @@ class CdasWs:
|
|
|
392
436
|
self.logger.info('response.text: %s', response.text)
|
|
393
437
|
return []
|
|
394
438
|
|
|
395
|
-
|
|
439
|
+
if self.logger.level <= logging.DEBUG:
|
|
440
|
+
self.logger.debug('response.text = %s', response.text)
|
|
441
|
+
|
|
442
|
+
instrument_response = ET.fromstring(response.text)
|
|
396
443
|
|
|
397
444
|
if self.logger.level <= logging.DEBUG:
|
|
398
|
-
self.logger.debug('
|
|
399
|
-
|
|
400
|
-
sort_keys=True))
|
|
445
|
+
self.logger.debug('instrument_response = %s',
|
|
446
|
+
ET.tostring(instrument_response))
|
|
401
447
|
|
|
402
|
-
|
|
403
|
-
|
|
448
|
+
instrument_types = []
|
|
449
|
+
for description in instrument_response.findall(\
|
|
450
|
+
'cdas:InstrumentTypeDescription', namespaces=NAMESPACES):
|
|
404
451
|
|
|
405
|
-
|
|
452
|
+
instrument_types.append({
|
|
453
|
+
'Name': description.find('cdas:Name',
|
|
454
|
+
namespaces=NAMESPACES).text
|
|
455
|
+
})
|
|
456
|
+
return instrument_types
|
|
406
457
|
|
|
407
458
|
|
|
408
459
|
def get_instruments(
|
|
@@ -452,17 +503,29 @@ class CdasWs:
|
|
|
452
503
|
self.logger.info('response.text: %s', response.text)
|
|
453
504
|
return []
|
|
454
505
|
|
|
455
|
-
|
|
506
|
+
if self.logger.level <= logging.DEBUG:
|
|
507
|
+
self.logger.debug('response.text = %s', response.text)
|
|
508
|
+
|
|
509
|
+
instruments_response = ET.fromstring(response.text)
|
|
456
510
|
|
|
457
511
|
if self.logger.level <= logging.DEBUG:
|
|
458
|
-
self.logger.debug('instruments = %s',
|
|
459
|
-
|
|
460
|
-
sort_keys=True))
|
|
512
|
+
self.logger.debug('instruments = %s', response.text)
|
|
513
|
+
#ET.indent(instruments_response, space=' '))
|
|
461
514
|
|
|
462
|
-
|
|
463
|
-
|
|
515
|
+
instruments = []
|
|
516
|
+
for instrument_description in instruments_response.findall(\
|
|
517
|
+
'cdas:InstrumentDescription', namespaces=NAMESPACES):
|
|
464
518
|
|
|
465
|
-
|
|
519
|
+
instruments.append({
|
|
520
|
+
'Name': instrument_description.find(\
|
|
521
|
+
'cdas:Name', namespaces=NAMESPACES).text,
|
|
522
|
+
'ShortDescription': instrument_description.find(\
|
|
523
|
+
'cdas:ShortDescription', namespaces=NAMESPACES).text,
|
|
524
|
+
'LongDescription': instrument_description.find(\
|
|
525
|
+
'cdas:LongDescription', namespaces=NAMESPACES).text
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
return instruments
|
|
466
529
|
|
|
467
530
|
|
|
468
531
|
def get_observatories(
|
|
@@ -512,17 +575,28 @@ class CdasWs:
|
|
|
512
575
|
self.logger.info('response.text: %s', response.text)
|
|
513
576
|
return []
|
|
514
577
|
|
|
515
|
-
|
|
578
|
+
if self.logger.level <= logging.DEBUG:
|
|
579
|
+
self.logger.debug('response.text = %s', response.text)
|
|
580
|
+
|
|
581
|
+
observatory_response = ET.fromstring(response.text)
|
|
516
582
|
|
|
517
583
|
if self.logger.level <= logging.DEBUG:
|
|
518
|
-
self.logger.debug('observatories = %s',
|
|
519
|
-
json.dumps(observatories, indent=4,
|
|
520
|
-
sort_keys=True))
|
|
584
|
+
self.logger.debug('observatories = %s', response.text)
|
|
521
585
|
|
|
522
|
-
|
|
523
|
-
|
|
586
|
+
observatories = []
|
|
587
|
+
|
|
588
|
+
for observatory in observatory_response.findall(\
|
|
589
|
+
'cdas:ObservatoryDescription', namespaces=NAMESPACES):
|
|
590
|
+
observatories.append({
|
|
591
|
+
'Name': observatory.find(\
|
|
592
|
+
'cdas:Name', namespaces=NAMESPACES).text,
|
|
593
|
+
'ShortDescription': observatory.find(\
|
|
594
|
+
'cdas:ShortDescription', namespaces=NAMESPACES).text,
|
|
595
|
+
'LongDescription': observatory.find(\
|
|
596
|
+
'cdas:LongDescription', namespaces=NAMESPACES).text
|
|
597
|
+
})
|
|
524
598
|
|
|
525
|
-
return observatories
|
|
599
|
+
return observatories
|
|
526
600
|
|
|
527
601
|
|
|
528
602
|
def get_observatory_groups_and_instruments(
|
|
@@ -567,17 +641,55 @@ class CdasWs:
|
|
|
567
641
|
self.logger.info('response.text: %s', response.text)
|
|
568
642
|
return []
|
|
569
643
|
|
|
570
|
-
observatories = response.json()
|
|
571
|
-
|
|
572
644
|
if self.logger.level <= logging.DEBUG:
|
|
573
|
-
self.logger.debug('
|
|
574
|
-
json.dumps(observatories, indent=4,
|
|
575
|
-
sort_keys=True))
|
|
645
|
+
self.logger.debug('response.text = %s', response.text)
|
|
576
646
|
|
|
577
|
-
|
|
578
|
-
return []
|
|
647
|
+
observatories_response = ET.fromstring(response.text)
|
|
579
648
|
|
|
580
|
-
|
|
649
|
+
if self.logger.level <= logging.DEBUG:
|
|
650
|
+
self.logger.debug('observatories = %s', response.text)
|
|
651
|
+
|
|
652
|
+
o_g_i_ds = []
|
|
653
|
+
|
|
654
|
+
for o_g_i_d in observatories_response.findall(\
|
|
655
|
+
'cdas:ObservatoryGroupInstrumentDescription',\
|
|
656
|
+
namespaces=NAMESPACES):
|
|
657
|
+
|
|
658
|
+
o_g_i_d_name = o_g_i_d.find('cdas:Name',
|
|
659
|
+
namespaces=NAMESPACES).text
|
|
660
|
+
o_is = []
|
|
661
|
+
for o_i in o_g_i_d.findall('cdas:ObservatoryInstruments',
|
|
662
|
+
namespaces=NAMESPACES):
|
|
663
|
+
|
|
664
|
+
o_i_name = o_i.find('cdas:Name',
|
|
665
|
+
namespaces=NAMESPACES).text
|
|
666
|
+
i_ds = []
|
|
667
|
+
for i_d in o_i.findall('cdas:InstrumentDescription',
|
|
668
|
+
namespaces=NAMESPACES):
|
|
669
|
+
i_d_name = i_d.find('cdas:Name',
|
|
670
|
+
namespaces=NAMESPACES).text
|
|
671
|
+
i_d_short_description = \
|
|
672
|
+
i_d.find('cdas:ShortDescription',
|
|
673
|
+
namespaces=NAMESPACES).text
|
|
674
|
+
i_d_long_description = \
|
|
675
|
+
i_d.find('cdas:LongDescription',
|
|
676
|
+
namespaces=NAMESPACES).text
|
|
677
|
+
i_ds.append({
|
|
678
|
+
'Name': i_d_name,
|
|
679
|
+
'ShortDescription': i_d_short_description,
|
|
680
|
+
'LongDescription': i_d_long_description
|
|
681
|
+
})
|
|
682
|
+
o_is.append({
|
|
683
|
+
'Name': o_i_name,
|
|
684
|
+
'InstrumentDescription': i_ds
|
|
685
|
+
})
|
|
686
|
+
|
|
687
|
+
o_g_i_ds.append({
|
|
688
|
+
'Name': o_g_i_d_name,
|
|
689
|
+
'ObservatoryInstruments': o_is
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
return o_g_i_ds
|
|
581
693
|
|
|
582
694
|
|
|
583
695
|
# pylint: disable=too-many-branches
|
|
@@ -610,11 +722,13 @@ class CdasWs:
|
|
|
610
722
|
that no datasets are eliminated based upon their instrument
|
|
611
723
|
value.<br>
|
|
612
724
|
<b>startDate</b> - a datetime specifying the start of a time
|
|
613
|
-
interval.
|
|
614
|
-
will begin infinitely
|
|
725
|
+
interval. See module note about timezone value. If this
|
|
726
|
+
parameter is ommited, the time interval will begin infinitely
|
|
727
|
+
in the past.<br>
|
|
615
728
|
<b>stopDate</b> - a datetime specifying the end of a time
|
|
616
|
-
interval.
|
|
617
|
-
will end infinitely
|
|
729
|
+
interval. See module note about timezone value. If this
|
|
730
|
+
parameter is omitted, the time interval will end infinitely
|
|
731
|
+
in the future.<br>
|
|
618
732
|
<b>idPattern</b> - a java.util.regex compatible regular
|
|
619
733
|
expression that must match the dataset's identifier value.
|
|
620
734
|
Omitting this parameter is equivalent to `.*`.<br>
|
|
@@ -702,16 +816,97 @@ class CdasWs:
|
|
|
702
816
|
self.logger.info('response.text: %s', response.text)
|
|
703
817
|
return []
|
|
704
818
|
|
|
705
|
-
datasets = response.json()
|
|
706
|
-
|
|
707
819
|
if self.logger.level <= logging.DEBUG:
|
|
708
|
-
self.logger.debug('
|
|
709
|
-
json.dumps(datasets, indent=4, sort_keys=True))
|
|
820
|
+
self.logger.debug('response.text = %s', response.text)
|
|
710
821
|
|
|
711
|
-
|
|
712
|
-
return []
|
|
822
|
+
dss = ET.fromstring(response.text)
|
|
713
823
|
|
|
714
|
-
|
|
824
|
+
if self.logger.level <= logging.DEBUG:
|
|
825
|
+
self.logger.debug('datasets = %s', response.text)
|
|
826
|
+
|
|
827
|
+
datasets = []
|
|
828
|
+
for ds in dss.findall('cdas:DatasetDescription',
|
|
829
|
+
namespaces=NAMESPACES):
|
|
830
|
+
|
|
831
|
+
observatory_groups = []
|
|
832
|
+
for o_g in ds.findall('cdas:ObservatoryGroup',
|
|
833
|
+
namespaces=NAMESPACES):
|
|
834
|
+
observatory_groups.append(o_g.text)
|
|
835
|
+
|
|
836
|
+
instrument_types = []
|
|
837
|
+
for i_t in ds.findall('cdas:InstrumentType',
|
|
838
|
+
namespaces=NAMESPACES):
|
|
839
|
+
instrument_types.append(i_t.text)
|
|
840
|
+
|
|
841
|
+
dataset_links = []
|
|
842
|
+
for d_l in ds.findall('cdas:DatasetLink',
|
|
843
|
+
namespaces=NAMESPACES):
|
|
844
|
+
dataset_links.append({
|
|
845
|
+
'Title': d_l.find('cdas:Title',
|
|
846
|
+
namespaces=NAMESPACES).text,
|
|
847
|
+
'Text': d_l.find('cdas:Text',
|
|
848
|
+
namespaces=NAMESPACES).text,
|
|
849
|
+
'Url': d_l.find('cdas:Url',
|
|
850
|
+
namespaces=NAMESPACES).text,
|
|
851
|
+
})
|
|
852
|
+
|
|
853
|
+
observatories = []
|
|
854
|
+
for obs_elem in ds.findall('cdas:Observatory',
|
|
855
|
+
namespaces=NAMESPACES):
|
|
856
|
+
observatories.append(obs_elem.text)
|
|
857
|
+
|
|
858
|
+
instruments = []
|
|
859
|
+
for instr_elem in ds.findall('cdas:Instrument',
|
|
860
|
+
namespaces=NAMESPACES):
|
|
861
|
+
instruments.append(instr_elem.text)
|
|
862
|
+
|
|
863
|
+
dataset = {
|
|
864
|
+
'Id': ds.find('cdas:Id', namespaces=NAMESPACES).text,
|
|
865
|
+
'Observatory': observatories,
|
|
866
|
+
'Instrument': instruments,
|
|
867
|
+
'ObservatoryGroup': observatory_groups,
|
|
868
|
+
'InstrumentType': instrument_types,
|
|
869
|
+
'Label': ds.find('cdas:Label',
|
|
870
|
+
namespaces=NAMESPACES).text,
|
|
871
|
+
'TimeInterval': {
|
|
872
|
+
'Start': ds.find('cdas:TimeInterval/cdas:Start',
|
|
873
|
+
namespaces=NAMESPACES).text,
|
|
874
|
+
'End': ds.find('cdas:TimeInterval/cdas:End',
|
|
875
|
+
namespaces=NAMESPACES).text
|
|
876
|
+
},
|
|
877
|
+
'PiName': ds.find('cdas:PiName',
|
|
878
|
+
namespaces=NAMESPACES).text,
|
|
879
|
+
'PiAffiliation': ds.find('cdas:PiAffiliation',
|
|
880
|
+
namespaces=NAMESPACES).text,
|
|
881
|
+
'Notes': ds.find('cdas:Notes',
|
|
882
|
+
namespaces=NAMESPACES).text,
|
|
883
|
+
'DatasetLink': dataset_links
|
|
884
|
+
}
|
|
885
|
+
doi = ds.find('cdas:Doi', namespaces=NAMESPACES)
|
|
886
|
+
if doi is not None:
|
|
887
|
+
dataset['Doi'] = doi.text
|
|
888
|
+
|
|
889
|
+
spase_resource_id = ds.find('cdas:SpaseResourceId',
|
|
890
|
+
namespaces=NAMESPACES)
|
|
891
|
+
if spase_resource_id is not None:
|
|
892
|
+
dataset['SpaseResourceId'] = spase_resource_id.text
|
|
893
|
+
|
|
894
|
+
additional_metadata = []
|
|
895
|
+
for add_meta in ds.findall('cdas:AdditionalMetadata',
|
|
896
|
+
namespaces=NAMESPACES):
|
|
897
|
+
meta_type = add_meta.attrib['Type']
|
|
898
|
+
value = add_meta.text
|
|
899
|
+
additional_metadata.append({
|
|
900
|
+
'Type': meta_type,
|
|
901
|
+
'value': value
|
|
902
|
+
})
|
|
903
|
+
|
|
904
|
+
if len(additional_metadata) > 0:
|
|
905
|
+
dataset['AdditionalMetadata'] = additional_metadata
|
|
906
|
+
|
|
907
|
+
datasets.append(dataset)
|
|
908
|
+
|
|
909
|
+
return sorted(datasets, key=itemgetter('Id'))
|
|
715
910
|
# pylint: enable=too-many-branches
|
|
716
911
|
|
|
717
912
|
|
|
@@ -782,24 +977,23 @@ class CdasWs:
|
|
|
782
977
|
self.logger.info('response.text: %s', response.text)
|
|
783
978
|
return []
|
|
784
979
|
|
|
785
|
-
inventory = response.json()
|
|
786
|
-
|
|
787
980
|
if self.logger.level <= logging.DEBUG:
|
|
788
|
-
self.logger.debug('
|
|
789
|
-
json.dumps(inventory, indent=4, sort_keys=True))
|
|
981
|
+
self.logger.debug('response.text = %s', response.text)
|
|
790
982
|
|
|
983
|
+
inventory = ET.fromstring(response.text)
|
|
791
984
|
intervals = []
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
985
|
+
for inventory_desc in inventory.findall(\
|
|
986
|
+
'cdas:InventoryDescription',
|
|
987
|
+
namespaces=NAMESPACES):
|
|
988
|
+
for time_interval in inventory_desc.findall(\
|
|
989
|
+
'cdas:TimeInterval',
|
|
990
|
+
namespaces=NAMESPACES):
|
|
799
991
|
intervals.append(
|
|
800
992
|
TimeInterval(
|
|
801
|
-
time_interval
|
|
802
|
-
|
|
993
|
+
time_interval.find('cdas:Start',
|
|
994
|
+
namespaces=NAMESPACES).text,
|
|
995
|
+
time_interval.find('cdas:End',
|
|
996
|
+
namespaces=NAMESPACES).text
|
|
803
997
|
)
|
|
804
998
|
)
|
|
805
999
|
|
|
@@ -872,12 +1066,36 @@ class CdasWs:
|
|
|
872
1066
|
self.logger.info('response.text: %s', response.text)
|
|
873
1067
|
return []
|
|
874
1068
|
|
|
875
|
-
|
|
1069
|
+
if self.logger.level <= logging.DEBUG:
|
|
1070
|
+
self.logger.debug('response.text = %s', response.text)
|
|
876
1071
|
|
|
877
|
-
|
|
878
|
-
|
|
1072
|
+
var_descriptions = ET.fromstring(response.text)
|
|
1073
|
+
|
|
1074
|
+
variables = []
|
|
1075
|
+
for var_description in var_descriptions.findall(\
|
|
1076
|
+
'cdas:VariableDescription',
|
|
1077
|
+
namespaces=NAMESPACES):
|
|
1078
|
+
name = var_description.find('cdas:Name',
|
|
1079
|
+
namespaces=NAMESPACES).text
|
|
1080
|
+
short_description = var_description.find(\
|
|
1081
|
+
'cdas:ShortDescription',
|
|
1082
|
+
namespaces=NAMESPACES).text
|
|
1083
|
+
if short_description is None:
|
|
1084
|
+
short_description = ''
|
|
1085
|
+
|
|
1086
|
+
long_description = var_description.find(\
|
|
1087
|
+
'cdas:LongDescription',
|
|
1088
|
+
namespaces=NAMESPACES).text
|
|
1089
|
+
if long_description is None:
|
|
1090
|
+
long_description = ''
|
|
879
1091
|
|
|
880
|
-
|
|
1092
|
+
variables.append({
|
|
1093
|
+
'Name': name,
|
|
1094
|
+
'ShortDescription': short_description,
|
|
1095
|
+
'LongDescription': long_description
|
|
1096
|
+
})
|
|
1097
|
+
|
|
1098
|
+
return variables
|
|
881
1099
|
|
|
882
1100
|
|
|
883
1101
|
def get_variable_names(
|
|
@@ -906,6 +1124,143 @@ class CdasWs:
|
|
|
906
1124
|
return variable_names
|
|
907
1125
|
|
|
908
1126
|
|
|
1127
|
+
@staticmethod
|
|
1128
|
+
def _get_thumbnail_description_dict(
|
|
1129
|
+
file_description_elem: ET.Element
|
|
1130
|
+
) -> Dict:
|
|
1131
|
+
"""
|
|
1132
|
+
Gets ThumbnailDescription dictionary representation from the
|
|
1133
|
+
given FileDescription element.
|
|
1134
|
+
|
|
1135
|
+
Parameters
|
|
1136
|
+
----------
|
|
1137
|
+
file_description_elem
|
|
1138
|
+
a FileDescription Element.
|
|
1139
|
+
Returns
|
|
1140
|
+
-------
|
|
1141
|
+
Dict
|
|
1142
|
+
a Dictionary representation of the ThumbnailDescription
|
|
1143
|
+
contained in the given FileDescription element.
|
|
1144
|
+
"""
|
|
1145
|
+
thumbnail_desc = file_description_elem.find(\
|
|
1146
|
+
'cdas:ThumbnailDescription',
|
|
1147
|
+
namespaces=NAMESPACES)
|
|
1148
|
+
if thumbnail_desc is not None:
|
|
1149
|
+
time_interval = thumbnail_desc.find('cdas:TimeInterval',
|
|
1150
|
+
namespaces=NAMESPACES)
|
|
1151
|
+
start = time_interval.find('cdas:Start',
|
|
1152
|
+
namespaces=NAMESPACES).text
|
|
1153
|
+
end = time_interval.find('cdas:End',
|
|
1154
|
+
namespaces=NAMESPACES).text
|
|
1155
|
+
return {
|
|
1156
|
+
'Name': thumbnail_desc.find('cdas:Name',
|
|
1157
|
+
namespaces=NAMESPACES).text,
|
|
1158
|
+
'Dataset': thumbnail_desc.find('cdas:Dataset',
|
|
1159
|
+
namespaces=NAMESPACES).text,
|
|
1160
|
+
'TimeInterval': {
|
|
1161
|
+
'Start': start,
|
|
1162
|
+
'End': end
|
|
1163
|
+
},
|
|
1164
|
+
'VarName': thumbnail_desc.find('cdas:VarName',
|
|
1165
|
+
namespaces=NAMESPACES).text,
|
|
1166
|
+
'Options': int(thumbnail_desc.find(\
|
|
1167
|
+
'cdas:Options',
|
|
1168
|
+
namespaces=NAMESPACES).text),
|
|
1169
|
+
'NumFrames': int(thumbnail_desc.find(\
|
|
1170
|
+
'cdas:NumFrames',
|
|
1171
|
+
namespaces=NAMESPACES).text),
|
|
1172
|
+
'NumRows': int(thumbnail_desc.find(\
|
|
1173
|
+
'cdas:NumRows',
|
|
1174
|
+
namespaces=NAMESPACES).text),
|
|
1175
|
+
'NumCols': int(thumbnail_desc.find(\
|
|
1176
|
+
'cdas:NumCols',
|
|
1177
|
+
namespaces=NAMESPACES).text),
|
|
1178
|
+
'TitleHeight': int(thumbnail_desc.find(\
|
|
1179
|
+
'cdas:TitleHeight',
|
|
1180
|
+
namespaces=NAMESPACES).text),
|
|
1181
|
+
'ThumbnailHeight': int(thumbnail_desc.find(\
|
|
1182
|
+
'cdas:ThumbnailHeight',
|
|
1183
|
+
namespaces=NAMESPACES).text),
|
|
1184
|
+
'ThumbnailWidth': int(thumbnail_desc.find(\
|
|
1185
|
+
'cdas:ThumbnailWidth',
|
|
1186
|
+
namespaces=NAMESPACES).text),
|
|
1187
|
+
'StartRecord': int(thumbnail_desc.find(\
|
|
1188
|
+
'cdas:StartRecord',
|
|
1189
|
+
namespaces=NAMESPACES).text),
|
|
1190
|
+
'MyScale': float(thumbnail_desc.find(\
|
|
1191
|
+
'cdas:MyScale',
|
|
1192
|
+
namespaces=NAMESPACES).text),
|
|
1193
|
+
'XyStep': float(thumbnail_desc.find(\
|
|
1194
|
+
'cdas:XyStep',
|
|
1195
|
+
namespaces=NAMESPACES).text)
|
|
1196
|
+
}
|
|
1197
|
+
return None
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
@staticmethod
|
|
1201
|
+
def _get_data_result_dict(
|
|
1202
|
+
xml_data_result: str
|
|
1203
|
+
) -> Dict:
|
|
1204
|
+
"""
|
|
1205
|
+
Gets DataResult dictionary representation from the
|
|
1206
|
+
given XML DataResult element.
|
|
1207
|
+
|
|
1208
|
+
Parameters
|
|
1209
|
+
----------
|
|
1210
|
+
xml_data_result
|
|
1211
|
+
XML representation of a DataResult.
|
|
1212
|
+
Returns
|
|
1213
|
+
-------
|
|
1214
|
+
Dict
|
|
1215
|
+
a Dictionary representation of the given XML representation
|
|
1216
|
+
of a DataResult.
|
|
1217
|
+
"""
|
|
1218
|
+
data_result = ET.fromstring(xml_data_result)
|
|
1219
|
+
file_descriptions = []
|
|
1220
|
+
for file_description in data_result.findall(\
|
|
1221
|
+
'cdas:FileDescription', namespaces=NAMESPACES):
|
|
1222
|
+
|
|
1223
|
+
dict_file_description = {
|
|
1224
|
+
'Name': file_description.find('cdas:Name',
|
|
1225
|
+
namespaces=NAMESPACES).text,
|
|
1226
|
+
'MimeType': file_description.find(\
|
|
1227
|
+
'cdas:MimeType',
|
|
1228
|
+
namespaces=NAMESPACES).text,
|
|
1229
|
+
'StartTime': file_description.find(\
|
|
1230
|
+
'cdas:StartTime',
|
|
1231
|
+
namespaces=NAMESPACES).text,
|
|
1232
|
+
'EndTime': file_description.find(\
|
|
1233
|
+
'cdas:EndTime',
|
|
1234
|
+
namespaces=NAMESPACES).text,
|
|
1235
|
+
'Length': int(file_description.find(\
|
|
1236
|
+
'cdas:Length',
|
|
1237
|
+
namespaces=NAMESPACES).text),
|
|
1238
|
+
'LastModified': file_description.find(\
|
|
1239
|
+
'cdas:LastModified',
|
|
1240
|
+
namespaces=NAMESPACES).text
|
|
1241
|
+
}
|
|
1242
|
+
thumbnail_dict = CdasWs._get_thumbnail_description_dict(\
|
|
1243
|
+
file_description)
|
|
1244
|
+
if thumbnail_dict is not None:
|
|
1245
|
+
dict_file_description['ThumbnailDescription'] = \
|
|
1246
|
+
thumbnail_dict
|
|
1247
|
+
|
|
1248
|
+
thumbnail_id_elem = file_description.find(\
|
|
1249
|
+
'cdas:ThumbnailId',
|
|
1250
|
+
namespaces=NAMESPACES)
|
|
1251
|
+
if thumbnail_id_elem is not None:
|
|
1252
|
+
dict_file_description['ThumbnailId'] = \
|
|
1253
|
+
thumbnail_id_elem.text
|
|
1254
|
+
|
|
1255
|
+
file_descriptions.append(dict_file_description)
|
|
1256
|
+
|
|
1257
|
+
if len(file_descriptions) > 0:
|
|
1258
|
+
return {
|
|
1259
|
+
'FileDescription': file_descriptions
|
|
1260
|
+
}
|
|
1261
|
+
return None
|
|
1262
|
+
|
|
1263
|
+
|
|
909
1264
|
def get_data_result(
|
|
910
1265
|
self,
|
|
911
1266
|
data_request: DataRequest,
|
|
@@ -953,18 +1308,10 @@ class CdasWs:
|
|
|
953
1308
|
response = self._session.post(url, data=data_request.json(),
|
|
954
1309
|
timeout=self._timeout)
|
|
955
1310
|
|
|
956
|
-
try:
|
|
957
|
-
data_result = response.json()
|
|
958
|
-
except ValueError:
|
|
959
|
-
# for example, a 503 from apache will not be json
|
|
960
|
-
self.logger.debug('Non-JSON response: %s', response.text)
|
|
961
|
-
|
|
962
|
-
if self.logger.level <= logging.DEBUG:
|
|
963
|
-
self.logger.debug('data_result = %s',
|
|
964
|
-
json.dumps(data_result, indent=4,
|
|
965
|
-
sort_keys=True))
|
|
966
1311
|
if response.status_code == 200:
|
|
967
1312
|
|
|
1313
|
+
data_result = CdasWs._get_data_result_dict(response.text)
|
|
1314
|
+
|
|
968
1315
|
if not data_result:
|
|
969
1316
|
return (response.status_code, None)
|
|
970
1317
|
|
|
@@ -1025,9 +1372,9 @@ class CdasWs:
|
|
|
1025
1372
|
variables
|
|
1026
1373
|
array containing names of variables to get.
|
|
1027
1374
|
start
|
|
1028
|
-
start time of data to get.
|
|
1375
|
+
start time of data to get. See module note about timezone.
|
|
1029
1376
|
end
|
|
1030
|
-
end time of data to get.
|
|
1377
|
+
end time of data to get. See module note about timezone.
|
|
1031
1378
|
keywords
|
|
1032
1379
|
optional keyword parameters as follows:<br>
|
|
1033
1380
|
<b>binData</b> - indicates that uniformly spaced values should
|
|
@@ -1065,7 +1412,7 @@ class CdasWs:
|
|
|
1065
1412
|
--------
|
|
1066
1413
|
CdasWs.get_data : In addition to what get_data_file does,
|
|
1067
1414
|
get_data also downloads and reads the data file into memory
|
|
1068
|
-
(SpaceData object).
|
|
1415
|
+
(SpaceData or xarray.Dataset object).
|
|
1069
1416
|
"""
|
|
1070
1417
|
# pylint: disable=too-many-locals
|
|
1071
1418
|
# pylint: disable=too-many-return-statements
|
|
@@ -1263,10 +1610,11 @@ class CdasWs:
|
|
|
1263
1610
|
ALL-VARIABLES may be used instead of specifying all the
|
|
1264
1611
|
individual variable names.
|
|
1265
1612
|
time0
|
|
1266
|
-
TimeInterval(s) or start time of data to get.
|
|
1613
|
+
TimeInterval(s) or start time of data to get. See module
|
|
1614
|
+
note about timezone.
|
|
1267
1615
|
time1
|
|
1268
1616
|
when time0 is not one or more TimeInterval(s), the end time
|
|
1269
|
-
of data to get.
|
|
1617
|
+
of data to get. See module note about timezone.
|
|
1270
1618
|
keywords
|
|
1271
1619
|
optional keyword parameters as follows:<br>
|
|
1272
1620
|
<b>binData</b> - indicates that uniformly spaced values should
|
|
@@ -1298,7 +1646,7 @@ class CdasWs:
|
|
|
1298
1646
|
Tuple
|
|
1299
1647
|
[0] contains a dictionary of HTTP and CDAS status information.
|
|
1300
1648
|
When successful, ['http']['status_code'] will be 200.<br>
|
|
1301
|
-
[1] contains the requested data (SpaceData or xarray.
|
|
1649
|
+
[1] contains the requested data (SpaceData or xarray.Dataset
|
|
1302
1650
|
object) or None.
|
|
1303
1651
|
Raises
|
|
1304
1652
|
------
|
|
@@ -1449,9 +1797,9 @@ class CdasWs:
|
|
|
1449
1797
|
variables
|
|
1450
1798
|
array containing names of variables to get.
|
|
1451
1799
|
start
|
|
1452
|
-
start time of data to get.
|
|
1800
|
+
start time of data to get. See module note about timezone.
|
|
1453
1801
|
end
|
|
1454
|
-
end time of data to get.
|
|
1802
|
+
end time of data to get. See module note about timezone.
|
|
1455
1803
|
options
|
|
1456
1804
|
graph options.
|
|
1457
1805
|
image_format
|
|
@@ -1552,9 +1900,9 @@ class CdasWs:
|
|
|
1552
1900
|
variables
|
|
1553
1901
|
array containing names of variables to get.
|
|
1554
1902
|
start
|
|
1555
|
-
start time of data to get.
|
|
1903
|
+
start time of data to get. See module note about timezone.
|
|
1556
1904
|
end
|
|
1557
|
-
end time of data to get.
|
|
1905
|
+
end time of data to get. See module note about timezone.
|
|
1558
1906
|
identifier
|
|
1559
1907
|
thumbnail identifier (returned in a previous get_graph
|
|
1560
1908
|
result).
|
|
@@ -1651,9 +1999,9 @@ class CdasWs:
|
|
|
1651
1999
|
variables
|
|
1652
2000
|
array containing names of variables to get.
|
|
1653
2001
|
start
|
|
1654
|
-
start time of data to get.
|
|
2002
|
+
start time of data to get. See module note about timezone.
|
|
1655
2003
|
end
|
|
1656
|
-
end time of data to get.
|
|
2004
|
+
end time of data to get. See module note about timezone.
|
|
1657
2005
|
compression
|
|
1658
2006
|
file compression.
|
|
1659
2007
|
text_format
|
|
@@ -1753,9 +2101,9 @@ class CdasWs:
|
|
|
1753
2101
|
variables
|
|
1754
2102
|
array containing names of variables to get.
|
|
1755
2103
|
start
|
|
1756
|
-
start time of data to get.
|
|
2104
|
+
start time of data to get. See module note about timezone.
|
|
1757
2105
|
end
|
|
1758
|
-
end time of data to get.
|
|
2106
|
+
end time of data to get. See module note about timezone.
|
|
1759
2107
|
keywords
|
|
1760
2108
|
optional keyword parameters as follows:<br>
|
|
1761
2109
|
<b>binData</b> - indicates that uniformly spaced values should
|
|
@@ -1848,9 +2196,9 @@ class CdasWs:
|
|
|
1848
2196
|
dataset
|
|
1849
2197
|
dataset identifier of data to get.
|
|
1850
2198
|
start
|
|
1851
|
-
start time of data to get.
|
|
2199
|
+
start time of data to get. See module note about timezone.
|
|
1852
2200
|
end
|
|
1853
|
-
end time of data to get.
|
|
2201
|
+
end time of data to get. See module note about timezone.
|
|
1854
2202
|
keywords
|
|
1855
2203
|
optional keyword parameters as follows:<br>
|
|
1856
2204
|
<b>progressCallback</b> - is a
|
|
@@ -1962,14 +2310,20 @@ class CdasWs:
|
|
|
1962
2310
|
self.logger.info('response.text: %s', response.text)
|
|
1963
2311
|
return (response.status_code, None)
|
|
1964
2312
|
|
|
1965
|
-
results = response.json()
|
|
1966
|
-
|
|
1967
2313
|
if self.logger.level <= logging.DEBUG:
|
|
1968
|
-
self.logger.debug('
|
|
1969
|
-
json.dumps(results,
|
|
1970
|
-
indent=4, sort_keys=True))
|
|
2314
|
+
self.logger.debug('response.text = %s', response.text)
|
|
1971
2315
|
|
|
1972
|
-
|
|
1973
|
-
|
|
2316
|
+
results = ET.fromstring(response.text)
|
|
2317
|
+
|
|
2318
|
+
ssc_id = []
|
|
2319
|
+
for ssc_id_elem in results.findall('SscId'):
|
|
2320
|
+
ssc_id.append(ssc_id_elem.text)
|
|
2321
|
+
|
|
2322
|
+
if len(ssc_id) == 0:
|
|
2323
|
+
result = None
|
|
2324
|
+
elif len(ssc_id) == 1:
|
|
2325
|
+
result = ssc_id[0]
|
|
2326
|
+
else:
|
|
2327
|
+
result = ssc_id
|
|
1974
2328
|
|
|
1975
|
-
return (response.status_code,
|
|
2329
|
+
return (response.status_code, result)
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
#
|
|
25
25
|
# NOSA HEADER END
|
|
26
26
|
#
|
|
27
|
-
# Copyright (c) 2019-
|
|
27
|
+
# Copyright (c) 2019-2024 United States Government as represented by
|
|
28
28
|
# the National Aeronautics and Space Administration. No copyright is
|
|
29
29
|
# claimed in the United States under Title 17, U.S.Code. All Other
|
|
30
30
|
# Rights Reserved.
|
|
@@ -36,7 +36,7 @@ Package defining classes to represent the DataRequestEntity and its
|
|
|
36
36
|
sub-classes from
|
|
37
37
|
<https://cdaweb.gsfc.nasa.gov/WebServices/REST/CDAS.xsd>.<br>
|
|
38
38
|
|
|
39
|
-
Copyright © 2019-
|
|
39
|
+
Copyright © 2019-2024 United States Government as represented by the
|
|
40
40
|
National Aeronautics and Space Administration. No copyright is claimed in
|
|
41
41
|
the United States under Title 17, U.S.Code. All Other Rights Reserved.
|
|
42
42
|
"""
|
|
@@ -378,6 +378,7 @@ class GraphOptions:
|
|
|
378
378
|
related variables from different datasets will result in the
|
|
379
379
|
same graphs being produced as when the option is not included.
|
|
380
380
|
"""
|
|
381
|
+
# pylint: disable=too-many-arguments
|
|
381
382
|
def __init__(self,
|
|
382
383
|
coarse_noise_filter: bool = False,
|
|
383
384
|
x_axis_width_factor: int = 3,
|
|
@@ -391,6 +392,7 @@ class GraphOptions:
|
|
|
391
392
|
self._y_axis_height_factor = y_axis_height_factor
|
|
392
393
|
self._combine = combine
|
|
393
394
|
self._overplot = overplot
|
|
395
|
+
# pylint: enable=too-many-arguments
|
|
394
396
|
|
|
395
397
|
|
|
396
398
|
@property
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
#
|
|
25
25
|
# NOSA HEADER END
|
|
26
26
|
#
|
|
27
|
-
# Copyright (c) 2018-
|
|
27
|
+
# Copyright (c) 2018-2024 United States Government as represented by
|
|
28
28
|
# the National Aeronautics and Space Administration. No copyright is
|
|
29
29
|
# claimed in the United States under Title 17, U.S.Code. All Other
|
|
30
30
|
# Rights Reserved.
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
Package defining a class to represent the TimeInterval class from
|
|
36
36
|
<https://cdaweb.gsfc.nasa.gov/WebServices/REST/CDAS.xsd>.<br>
|
|
37
37
|
|
|
38
|
-
Copyright © 2018-
|
|
38
|
+
Copyright © 2018-2024 United States Government as represented by the
|
|
39
39
|
National Aeronautics and Space Administration. No copyright is claimed in
|
|
40
40
|
the United States under Title 17, U.S.Code. All Other Rights Reserved.
|
|
41
41
|
"""
|
|
@@ -53,6 +53,14 @@ class TimeInterval:
|
|
|
53
53
|
A class representing a TimeInterval class from
|
|
54
54
|
<https://cdaweb.gsfc.nasa.gov/WebServices/REST/CDAS.xsd>.
|
|
55
55
|
|
|
56
|
+
Notes
|
|
57
|
+
-----
|
|
58
|
+
Since CDAS data uses datetime values with a UTC timezone,
|
|
59
|
+
the resulting start and end properties have a UTC timezone. If
|
|
60
|
+
the given values' timezone is not UTC, the start/end values are
|
|
61
|
+
adjusted to UTC. If the given value has no timezone (is naive) a
|
|
62
|
+
UTC value is set.
|
|
63
|
+
|
|
56
64
|
Parameters
|
|
57
65
|
----------
|
|
58
66
|
start
|
|
@@ -135,7 +143,11 @@ class TimeInterval:
|
|
|
135
143
|
@staticmethod
|
|
136
144
|
def get_datetime(value: Union[datetime, str]) -> datetime:
|
|
137
145
|
"""
|
|
138
|
-
Produces a datetime representation of the given value.
|
|
146
|
+
Produces a datetime representation of the given value. The
|
|
147
|
+
returned datetime always has a timezone of timezone.utc. If
|
|
148
|
+
the given value's timezone is not utc, the return value is
|
|
149
|
+
adjusted to utc. If the given value has no timezone (is naive)
|
|
150
|
+
a utc value is set.
|
|
139
151
|
|
|
140
152
|
Parameters
|
|
141
153
|
----------
|
|
@@ -144,7 +156,8 @@ class TimeInterval:
|
|
|
144
156
|
Returns
|
|
145
157
|
-------
|
|
146
158
|
datetime
|
|
147
|
-
datetime representation of the given value
|
|
159
|
+
datetime representation of the given value in the UTC
|
|
160
|
+
timezone.
|
|
148
161
|
Raises
|
|
149
162
|
------
|
|
150
163
|
ValueError
|
|
@@ -157,9 +170,11 @@ class TimeInterval:
|
|
|
157
170
|
else:
|
|
158
171
|
raise ValueError('unrecognized datetime value')
|
|
159
172
|
|
|
160
|
-
datetime_value.
|
|
173
|
+
if datetime_value.tzinfo is None or \
|
|
174
|
+
datetime_value.tzinfo.utcoffset(None) is None:
|
|
175
|
+
return datetime_value.replace(tzinfo=timezone.utc)
|
|
161
176
|
|
|
162
|
-
return datetime_value
|
|
177
|
+
return datetime_value.astimezone(timezone.utc)
|
|
163
178
|
|
|
164
179
|
|
|
165
180
|
@staticmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cdasws
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.3
|
|
4
4
|
Summary: NASA's Coordinated Data Analysis System Web Service Client Library
|
|
5
5
|
Home-page: https://cdaweb.gsfc.nasa.gov/WebServices/REST
|
|
6
6
|
Author: Bernie Harris
|
|
@@ -125,5 +125,5 @@ Classifier: Programming Language :: Python
|
|
|
125
125
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
126
126
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
127
127
|
Description-Content-Type: text/markdown
|
|
128
|
-
Provides-Extra: xarray
|
|
129
128
|
Provides-Extra: spdm
|
|
129
|
+
Provides-Extra: xarray
|
|
@@ -10,7 +10,7 @@ README = (HERE / "README.md").read_text()
|
|
|
10
10
|
# This call to setup() does all the work
|
|
11
11
|
setup(
|
|
12
12
|
name="cdasws",
|
|
13
|
-
version="1.
|
|
13
|
+
version="1.8.3",
|
|
14
14
|
description="NASA's Coordinated Data Analysis System Web Service Client Library",
|
|
15
15
|
long_description=README,
|
|
16
16
|
long_description_content_type="text/markdown",
|
|
@@ -19,6 +19,7 @@ setup(
|
|
|
19
19
|
author_email="NASA-SPDF-Support@nasa.onmicrosoft.com",
|
|
20
20
|
license="NOSA",
|
|
21
21
|
packages=["cdasws"],
|
|
22
|
+
# python_requires=[">3.4"]
|
|
22
23
|
# packages=find_packages(exclude=["tests"]),
|
|
23
24
|
# packages=find_packages(),
|
|
24
25
|
include_package_data=True,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|