cdasws 1.8.11__tar.gz → 1.8.13__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.
@@ -17,7 +17,7 @@ Government Agency Original Software Designation: GSC-14730-1
17
17
  Government Agency Original Software Title: "Space Physics Data Facility Web Services"
18
18
  User Registration Requested. Please Visit http://spdf.gsfc.nasa.gov/
19
19
  Government Agency Point of Contact for Original Software:
20
- gsfc-spdf-support@lists.nasa.gov
20
+ NASA-SPDF-Support@nasa.onmicrosoft.com
21
21
 
22
22
 
23
23
  1. DEFINITIONS
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdasws
3
- Version: 1.8.11
3
+ Version: 1.8.13
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
@@ -16,6 +16,7 @@ Classifier: Intended Audience :: System Administrators
16
16
  Classifier: License :: OSI Approved :: NASA Open Source Agreement v1.3 (NASA-1.3)
17
17
  Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3
19
20
  Classifier: Topic :: Scientific/Engineering :: Physics
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
22
  Description-Content-Type: text/markdown
@@ -57,6 +58,8 @@ and can return data from any of
57
58
  [pandas.DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)
58
59
  with all source and
59
60
  [ISTP/SPDF](https://spdf.gsfc.nasa.gov/sp_use_of_cdf.html) metadata.
61
+ Note that this package is included in the [HelioCloud](https://heliocloud.org/)
62
+ base image, so there is no need to install it there.
60
63
  Frequently asked questions concerning this library are at
61
64
  [FAQ](https://cdaweb.gsfc.nasa.gov/WebServices/REST/py/FAQ.html).
62
65
  For more general details about the CDAS web services, see
@@ -13,6 +13,8 @@ and can return data from any of
13
13
  [pandas.DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)
14
14
  with all source and
15
15
  [ISTP/SPDF](https://spdf.gsfc.nasa.gov/sp_use_of_cdf.html) metadata.
16
+ Note that this package is included in the [HelioCloud](https://heliocloud.org/)
17
+ base image, so there is no need to install it there.
16
18
  Frequently asked questions concerning this library are at
17
19
  [FAQ](https://cdaweb.gsfc.nasa.gov/WebServices/REST/py/FAQ.html).
18
20
  For more general details about the CDAS web services, see
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env python3
2
+
3
+ #
4
+ # NOSA HEADER START
5
+ #
6
+ # The contents of this file are subject to the terms of the NASA Open
7
+ # Source Agreement (NOSA), Version 1.3 only (the "Agreement"). You may
8
+ # not use this file except in compliance with the Agreement.
9
+ #
10
+ # You can obtain a copy of the agreement at
11
+ # docs/NASA_Open_Source_Agreement_1.3.txt
12
+ # or
13
+ # https://cdaweb.gsfc.nasa.gov/WebServices/NASA_Open_Source_Agreement_1.3.txt.
14
+ #
15
+ # See the Agreement for the specific language governing permissions
16
+ # and limitations under the Agreement.
17
+ #
18
+ # When distributing Covered Code, include this NOSA HEADER in each
19
+ # file and include the Agreement file at
20
+ # docs/NASA_Open_Source_Agreement_1.3.txt. If applicable, add the
21
+ # following below this NOSA HEADER, with the fields enclosed by
22
+ # brackets "[]" replaced with your own identifying information:
23
+ # Portions Copyright [yyyy] [name of copyright owner]
24
+ #
25
+ # NOSA HEADER END
26
+ #
27
+ # Copyright (c) 2018-2026 United States Government as represented by
28
+ # the National Aeronautics and Space Administration. No copyright is
29
+ # claimed in the United States under Title 17, U.S.Code. All Other
30
+ # Rights Reserved.
31
+ #
32
+
33
+
34
+ """
35
+ Package for accessing the Coordinate Data Analysis System (CDAS)
36
+ web services <https://cdaweb.gsfc.nasa.gov/WebServices/REST/>.<br>
37
+
38
+ Copyright &copy; 2018-2026 United States Government as represented by the
39
+ National Aeronautics and Space Administration. No copyright is claimed in
40
+ the United States under Title 17, U.S.Code. All Other Rights Reserved.
41
+
42
+ Notes
43
+ -----
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>
55
+ """
56
+
57
+
58
+ __version__ = "1.8.13"
59
+
60
+
61
+ #
62
+ # Limit on the number of times an HTTP request which returns a
63
+ # 429 or 503 status with a Retry-After header will be retried.
64
+ #
65
+ RETRY_LIMIT = 100
66
+
67
+ #
68
+ # XML schema namespace
69
+ #
70
+ NS = 'http://cdaweb.gsfc.nasa.gov/schema'
71
+ #
72
+ # XHTML schema namespace
73
+ #
74
+ XHTML_NS = 'http://www.w3.org/1999/xhtml'
75
+ #
76
+ # All namespaces found in responses.
77
+ #
78
+ NAMESPACES = {
79
+ 'cdas': NS,
80
+ 'xhtml': XHTML_NS
81
+ }
82
+ #
83
+ # For backward compatibility with cdasws versions < 1.8.12.
84
+ #
85
+ from cdasws.cdasws import * # pylint: disable=wrong-import-position
@@ -24,7 +24,7 @@
24
24
  #
25
25
  # NOSA HEADER END
26
26
  #
27
- # Copyright (c) 2018-2025 United States Government as represented by
27
+ # Copyright (c) 2018-2026 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.
@@ -34,7 +34,7 @@
34
34
  Example Coordinate Data Analysis System (CDAS) web service client.
35
35
  Includes example calls to most of the web services.
36
36
 
37
- Copyright &copy; 2018-2025 United States Government as represented by the
37
+ Copyright &copy; 2018-2026 United States Government as represented by the
38
38
  National Aeronautics and Space Administration. No copyright is claimed in
39
39
  the United States under Title 17, U.S.Code. All Other Rights Reserved.
40
40
  """
@@ -48,10 +48,11 @@ import logging.config
48
48
  from typing import List
49
49
  import urllib3
50
50
  #import matplotlib.pyplot as plt
51
- from cdasws import CdasWs
51
+ from cdasws.cdasws import CdasWs
52
52
  from cdasws.timeinterval import TimeInterval
53
53
  from cdasws.datarequest import GraphOptions, ImageFormat, Overplot, TextFormat
54
54
  from cdasws.datarepresentation import DataRepresentation
55
+ from cdasws.doi import get_doi_landing_page_url
55
56
 
56
57
 
57
58
  logging.basicConfig()
@@ -147,7 +148,7 @@ def example(
147
148
 
148
149
  cdas = CdasWs(endpoint=endpoint, ca_certs=ca_certs,
149
150
  disable_ssl_certificate_validation=
150
- disable_ssl_certificate_validation,
151
+ disable_ssl_certificate_validation,
151
152
  disable_cache = disable_cache, user_agent='Example')
152
153
 
153
154
  print(cdas.get_observatory_groups(
@@ -166,7 +167,7 @@ def example(
166
167
  #print(' ', json.dumps(dataset, indent=4))
167
168
 
168
169
  print('DOI landing page:',
169
- cdas.get_doi_landing_page_url('10.48322/e0dc-0h53'))
170
+ get_doi_landing_page_url('10.48322/e0dc-0h53'))
170
171
 
171
172
  print('citation = ' + cdas.get_citation('10.48322/541v-1f57'))
172
173
 
@@ -24,7 +24,7 @@
24
24
  #
25
25
  # NOSA HEADER END
26
26
  #
27
- # Copyright (c) 2018-2025 United States Government as represented by
27
+ # Copyright (c) 2018-2026 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.
@@ -32,10 +32,10 @@
32
32
 
33
33
 
34
34
  """
35
- Package for accessing the Coordinate Data Analysis System (CDAS)
35
+ Module for accessing the Coordinate Data Analysis System (CDAS)
36
36
  web services <https://cdaweb.gsfc.nasa.gov/WebServices/REST/>.<br>
37
37
 
38
- Copyright &copy; 2018-2025 United States Government as represented by the
38
+ Copyright &copy; 2018-2026 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
 
@@ -60,19 +60,19 @@ import os
60
60
  import platform
61
61
  import logging
62
62
  import re
63
- from importlib.util import find_spec
63
+ #from importlib.util import find_spec
64
64
  import urllib.parse
65
65
  from urllib.parse import urlparse
66
- import json
66
+ #import json
67
67
  from operator import itemgetter
68
68
  import time
69
- from datetime import datetime, timedelta, timezone
69
+ from datetime import datetime, timedelta
70
70
  import xml.etree.ElementTree as ET
71
71
  from tempfile import mkstemp
72
72
  from typing import Any, Callable, Dict, List, Tuple, Union
73
73
 
74
74
  import requests
75
- import dateutil.parser
75
+ #import dateutil.parser
76
76
 
77
77
  from cdasws.datarepresentation import DataRepresentation
78
78
  from cdasws.datarequest import AudioRequest, DataRequest
@@ -80,6 +80,8 @@ from cdasws.datarequest import CdfFormat, CdfRequest, Compression
80
80
  from cdasws.datarequest import ImageFormat, GraphOptions, GraphRequest
81
81
  from cdasws.datarequest import TextFormat, TextRequest, ThumbnailRequest
82
82
  from cdasws.timeinterval import TimeInterval
83
+ from cdasws.doi import get_doi_landing_page_url
84
+ from cdasws import __version__, RETRY_LIMIT, NAMESPACES as NS
83
85
 
84
86
 
85
87
  # requires python >= 3.4
@@ -144,32 +146,6 @@ except ImportError:
144
146
  CACHE_AVAILABLE = False
145
147
 
146
148
 
147
- __version__ = "1.8.11"
148
-
149
-
150
- #
151
- # Limit on the number of times an HTTP request which returns a
152
- # 429 or 503 status with a Retry-After header will be retried.
153
- #
154
- RETRY_LIMIT = 100
155
-
156
- #
157
- # XML schema namespace
158
- #
159
- NS = 'http://cdaweb.gsfc.nasa.gov/schema'
160
- #
161
- # XHTML schema namespace
162
- #
163
- XHTML_NS = 'http://www.w3.org/1999/xhtml'
164
- #
165
- # All namespaces found in responses.
166
- #
167
- NAMESPACES = {
168
- 'cdas': NS,
169
- 'xhtml': XHTML_NS
170
- }
171
-
172
-
173
149
  def _get_data_progress(
174
150
  progress: float,
175
151
  msg: str,
@@ -389,17 +365,17 @@ class CdasWs:
389
365
 
390
366
  observatory_group_descriptions = []
391
367
  for description in observatory_response.findall(\
392
- 'cdas:ObservatoryGroupDescription', namespaces=NAMESPACES):
368
+ 'cdas:ObservatoryGroupDescription', namespaces=NS):
393
369
 
394
370
  observatory_ids = []
395
371
  for observatory_id in description.findall(\
396
- 'cdas:ObservatoryId', namespaces=NAMESPACES):
372
+ 'cdas:ObservatoryId', namespaces=NS):
397
373
 
398
374
  observatory_ids.append(observatory_id.text)
399
375
 
400
376
  observatory_group_descriptions.append({
401
377
  'Name': description.find(\
402
- 'cdas:Name', namespaces=NAMESPACES).text,
378
+ 'cdas:Name', namespaces=NS).text,
403
379
  'ObservatoryId': observatory_ids
404
380
  })
405
381
 
@@ -464,11 +440,11 @@ class CdasWs:
464
440
 
465
441
  instrument_types = []
466
442
  for description in instrument_response.findall(\
467
- 'cdas:InstrumentTypeDescription', namespaces=NAMESPACES):
443
+ 'cdas:InstrumentTypeDescription', namespaces=NS):
468
444
 
469
445
  instrument_types.append({
470
446
  'Name': description.find('cdas:Name',
471
- namespaces=NAMESPACES).text
447
+ namespaces=NS).text
472
448
  })
473
449
  return instrument_types
474
450
 
@@ -531,15 +507,15 @@ class CdasWs:
531
507
 
532
508
  instruments = []
533
509
  for instrument_description in instruments_response.findall(\
534
- 'cdas:InstrumentDescription', namespaces=NAMESPACES):
510
+ 'cdas:InstrumentDescription', namespaces=NS):
535
511
 
536
512
  instruments.append({
537
513
  'Name': instrument_description.find(\
538
- 'cdas:Name', namespaces=NAMESPACES).text,
514
+ 'cdas:Name', namespaces=NS).text,
539
515
  'ShortDescription': instrument_description.find(\
540
- 'cdas:ShortDescription', namespaces=NAMESPACES).text,
516
+ 'cdas:ShortDescription', namespaces=NS).text,
541
517
  'LongDescription': instrument_description.find(\
542
- 'cdas:LongDescription', namespaces=NAMESPACES).text
518
+ 'cdas:LongDescription', namespaces=NS).text
543
519
  })
544
520
 
545
521
  return instruments
@@ -603,14 +579,14 @@ class CdasWs:
603
579
  observatories = []
604
580
 
605
581
  for observatory in observatory_response.findall(\
606
- 'cdas:ObservatoryDescription', namespaces=NAMESPACES):
582
+ 'cdas:ObservatoryDescription', namespaces=NS):
607
583
  observatories.append({
608
584
  'Name': observatory.find(\
609
- 'cdas:Name', namespaces=NAMESPACES).text,
585
+ 'cdas:Name', namespaces=NS).text,
610
586
  'ShortDescription': observatory.find(\
611
- 'cdas:ShortDescription', namespaces=NAMESPACES).text,
587
+ 'cdas:ShortDescription', namespaces=NS).text,
612
588
  'LongDescription': observatory.find(\
613
- 'cdas:LongDescription', namespaces=NAMESPACES).text
589
+ 'cdas:LongDescription', namespaces=NS).text
614
590
  })
615
591
 
616
592
  return observatories
@@ -670,27 +646,27 @@ class CdasWs:
670
646
 
671
647
  for o_g_i_d in observatories_response.findall(\
672
648
  'cdas:ObservatoryGroupInstrumentDescription',\
673
- namespaces=NAMESPACES):
649
+ namespaces=NS):
674
650
 
675
651
  o_g_i_d_name = o_g_i_d.find('cdas:Name',
676
- namespaces=NAMESPACES).text
652
+ namespaces=NS).text
677
653
  o_is = []
678
654
  for o_i in o_g_i_d.findall('cdas:ObservatoryInstruments',
679
- namespaces=NAMESPACES):
655
+ namespaces=NS):
680
656
 
681
657
  o_i_name = o_i.find('cdas:Name',
682
- namespaces=NAMESPACES).text
658
+ namespaces=NS).text
683
659
  i_ds = []
684
660
  for i_d in o_i.findall('cdas:InstrumentDescription',
685
- namespaces=NAMESPACES):
661
+ namespaces=NS):
686
662
  i_d_name = i_d.find('cdas:Name',
687
- namespaces=NAMESPACES).text
663
+ namespaces=NS).text
688
664
  i_d_short_description = \
689
665
  i_d.find('cdas:ShortDescription',
690
- namespaces=NAMESPACES).text
666
+ namespaces=NS).text
691
667
  i_d_long_description = \
692
668
  i_d.find('cdas:LongDescription',
693
- namespaces=NAMESPACES).text
669
+ namespaces=NS).text
694
670
  i_ds.append({
695
671
  'Name': i_d_name,
696
672
  'ShortDescription': i_d_short_description,
@@ -851,74 +827,74 @@ class CdasWs:
851
827
 
852
828
  datasets = []
853
829
  for ds in dss.findall('cdas:DatasetDescription',
854
- namespaces=NAMESPACES):
830
+ namespaces=NS):
855
831
 
856
832
  observatory_groups = []
857
833
  for o_g in ds.findall('cdas:ObservatoryGroup',
858
- namespaces=NAMESPACES):
834
+ namespaces=NS):
859
835
  observatory_groups.append(o_g.text)
860
836
 
861
837
  instrument_types = []
862
838
  for i_t in ds.findall('cdas:InstrumentType',
863
- namespaces=NAMESPACES):
839
+ namespaces=NS):
864
840
  instrument_types.append(i_t.text)
865
841
 
866
842
  dataset_links = []
867
843
  for d_l in ds.findall('cdas:DatasetLink',
868
- namespaces=NAMESPACES):
844
+ namespaces=NS):
869
845
  dataset_links.append({
870
846
  'Title': d_l.find('cdas:Title',
871
- namespaces=NAMESPACES).text,
847
+ namespaces=NS).text,
872
848
  'Text': d_l.find('cdas:Text',
873
- namespaces=NAMESPACES).text,
849
+ namespaces=NS).text,
874
850
  'Url': d_l.find('cdas:Url',
875
- namespaces=NAMESPACES).text,
851
+ namespaces=NS).text,
876
852
  })
877
853
 
878
854
  observatories = []
879
855
  for obs_elem in ds.findall('cdas:Observatory',
880
- namespaces=NAMESPACES):
856
+ namespaces=NS):
881
857
  observatories.append(obs_elem.text)
882
858
 
883
859
  instruments = []
884
860
  for instr_elem in ds.findall('cdas:Instrument',
885
- namespaces=NAMESPACES):
861
+ namespaces=NS):
886
862
  instruments.append(instr_elem.text)
887
863
 
888
864
  dataset = {
889
- 'Id': ds.find('cdas:Id', namespaces=NAMESPACES).text,
865
+ 'Id': ds.find('cdas:Id', namespaces=NS).text,
890
866
  'Observatory': observatories,
891
867
  'Instrument': instruments,
892
868
  'ObservatoryGroup': observatory_groups,
893
869
  'InstrumentType': instrument_types,
894
870
  'Label': ds.find('cdas:Label',
895
- namespaces=NAMESPACES).text,
871
+ namespaces=NS).text,
896
872
  'TimeInterval': {
897
873
  'Start': ds.find('cdas:TimeInterval/cdas:Start',
898
- namespaces=NAMESPACES).text,
874
+ namespaces=NS).text,
899
875
  'End': ds.find('cdas:TimeInterval/cdas:End',
900
- namespaces=NAMESPACES).text
876
+ namespaces=NS).text
901
877
  },
902
878
  'PiName': ds.find('cdas:PiName',
903
- namespaces=NAMESPACES).text,
879
+ namespaces=NS).text,
904
880
  'PiAffiliation': ds.find('cdas:PiAffiliation',
905
- namespaces=NAMESPACES).text,
881
+ namespaces=NS).text,
906
882
  'Notes': ds.find('cdas:Notes',
907
- namespaces=NAMESPACES).text,
883
+ namespaces=NS).text,
908
884
  'DatasetLink': dataset_links
909
885
  }
910
- doi = ds.find('cdas:Doi', namespaces=NAMESPACES)
886
+ doi = ds.find('cdas:Doi', namespaces=NS)
911
887
  if doi is not None:
912
888
  dataset['Doi'] = doi.text
913
889
 
914
890
  spase_resource_id = ds.find('cdas:SpaseResourceId',
915
- namespaces=NAMESPACES)
891
+ namespaces=NS)
916
892
  if spase_resource_id is not None:
917
893
  dataset['SpaseResourceId'] = spase_resource_id.text
918
894
 
919
895
  additional_metadata = []
920
896
  for add_meta in ds.findall('cdas:AdditionalMetadata',
921
- namespaces=NAMESPACES):
897
+ namespaces=NS):
922
898
  meta_type = add_meta.attrib['Type']
923
899
  value = add_meta.text
924
900
  additional_metadata.append({
@@ -943,6 +919,9 @@ class CdasWs:
943
919
  Returns a URL to the given Digital Object Identifier's landing
944
920
  page (metadata for the DOI).
945
921
 
922
+ Note: this method is deprecated. You should call
923
+ doi.get_doi_landing_page_url directly.
924
+
946
925
  Parameters
947
926
  ----------
948
927
  doi
@@ -953,9 +932,7 @@ class CdasWs:
953
932
  A URL to the DOI's landing page.
954
933
  """
955
934
 
956
- if not doi.startswith('http'):
957
- return 'https://doi.org/' + doi
958
- return doi
935
+ return get_doi_landing_page_url(doi)
959
936
 
960
937
 
961
938
  @staticmethod
@@ -1034,16 +1011,16 @@ class CdasWs:
1034
1011
  intervals = []
1035
1012
  for inventory_desc in inventory.findall(\
1036
1013
  'cdas:InventoryDescription',
1037
- namespaces=NAMESPACES):
1014
+ namespaces=NS):
1038
1015
  for time_interval in inventory_desc.findall(\
1039
1016
  'cdas:TimeInterval',
1040
- namespaces=NAMESPACES):
1017
+ namespaces=NS):
1041
1018
  intervals.append(
1042
1019
  TimeInterval(
1043
1020
  time_interval.find('cdas:Start',
1044
- namespaces=NAMESPACES).text,
1021
+ namespaces=NS).text,
1045
1022
  time_interval.find('cdas:End',
1046
- namespaces=NAMESPACES).text
1023
+ namespaces=NS).text
1047
1024
  )
1048
1025
  )
1049
1026
 
@@ -1124,18 +1101,18 @@ class CdasWs:
1124
1101
  variables = []
1125
1102
  for var_description in var_descriptions.findall(\
1126
1103
  'cdas:VariableDescription',
1127
- namespaces=NAMESPACES):
1104
+ namespaces=NS):
1128
1105
  name = var_description.find('cdas:Name',
1129
- namespaces=NAMESPACES).text
1106
+ namespaces=NS).text
1130
1107
  short_description = var_description.find(\
1131
1108
  'cdas:ShortDescription',
1132
- namespaces=NAMESPACES).text
1109
+ namespaces=NS).text
1133
1110
  if short_description is None:
1134
1111
  short_description = ''
1135
1112
 
1136
1113
  long_description = var_description.find(\
1137
1114
  'cdas:LongDescription',
1138
- namespaces=NAMESPACES).text
1115
+ namespaces=NS).text
1139
1116
  if long_description is None:
1140
1117
  long_description = ''
1141
1118
 
@@ -1194,55 +1171,55 @@ class CdasWs:
1194
1171
  """
1195
1172
  thumbnail_desc = file_description_elem.find(\
1196
1173
  'cdas:ThumbnailDescription',
1197
- namespaces=NAMESPACES)
1174
+ namespaces=NS)
1198
1175
  if thumbnail_desc is not None:
1199
1176
  time_interval = thumbnail_desc.find('cdas:TimeInterval',
1200
- namespaces=NAMESPACES)
1177
+ namespaces=NS)
1201
1178
  start = time_interval.find('cdas:Start',
1202
- namespaces=NAMESPACES).text
1179
+ namespaces=NS).text
1203
1180
  end = time_interval.find('cdas:End',
1204
- namespaces=NAMESPACES).text
1181
+ namespaces=NS).text
1205
1182
  return {
1206
1183
  'Name': thumbnail_desc.find('cdas:Name',
1207
- namespaces=NAMESPACES).text,
1184
+ namespaces=NS).text,
1208
1185
  'Dataset': thumbnail_desc.find('cdas:Dataset',
1209
- namespaces=NAMESPACES).text,
1186
+ namespaces=NS).text,
1210
1187
  'TimeInterval': {
1211
1188
  'Start': start,
1212
1189
  'End': end
1213
1190
  },
1214
1191
  'VarName': thumbnail_desc.find('cdas:VarName',
1215
- namespaces=NAMESPACES).text,
1192
+ namespaces=NS).text,
1216
1193
  'Options': int(thumbnail_desc.find(\
1217
1194
  'cdas:Options',
1218
- namespaces=NAMESPACES).text),
1195
+ namespaces=NS).text),
1219
1196
  'NumFrames': int(thumbnail_desc.find(\
1220
1197
  'cdas:NumFrames',
1221
- namespaces=NAMESPACES).text),
1198
+ namespaces=NS).text),
1222
1199
  'NumRows': int(thumbnail_desc.find(\
1223
1200
  'cdas:NumRows',
1224
- namespaces=NAMESPACES).text),
1201
+ namespaces=NS).text),
1225
1202
  'NumCols': int(thumbnail_desc.find(\
1226
1203
  'cdas:NumCols',
1227
- namespaces=NAMESPACES).text),
1204
+ namespaces=NS).text),
1228
1205
  'TitleHeight': int(thumbnail_desc.find(\
1229
1206
  'cdas:TitleHeight',
1230
- namespaces=NAMESPACES).text),
1207
+ namespaces=NS).text),
1231
1208
  'ThumbnailHeight': int(thumbnail_desc.find(\
1232
1209
  'cdas:ThumbnailHeight',
1233
- namespaces=NAMESPACES).text),
1210
+ namespaces=NS).text),
1234
1211
  'ThumbnailWidth': int(thumbnail_desc.find(\
1235
1212
  'cdas:ThumbnailWidth',
1236
- namespaces=NAMESPACES).text),
1213
+ namespaces=NS).text),
1237
1214
  'StartRecord': int(thumbnail_desc.find(\
1238
1215
  'cdas:StartRecord',
1239
- namespaces=NAMESPACES).text),
1216
+ namespaces=NS).text),
1240
1217
  'MyScale': float(thumbnail_desc.find(\
1241
1218
  'cdas:MyScale',
1242
- namespaces=NAMESPACES).text),
1219
+ namespaces=NS).text),
1243
1220
  'XyStep': float(thumbnail_desc.find(\
1244
1221
  'cdas:XyStep',
1245
- namespaces=NAMESPACES).text)
1222
+ namespaces=NS).text)
1246
1223
  }
1247
1224
  return None
1248
1225
 
@@ -1268,26 +1245,26 @@ class CdasWs:
1268
1245
  data_result = ET.fromstring(xml_data_result)
1269
1246
  file_descriptions = []
1270
1247
  for file_description in data_result.findall(\
1271
- 'cdas:FileDescription', namespaces=NAMESPACES):
1248
+ 'cdas:FileDescription', namespaces=NS):
1272
1249
 
1273
1250
  dict_file_description = {
1274
1251
  'Name': file_description.find('cdas:Name',
1275
- namespaces=NAMESPACES).text,
1252
+ namespaces=NS).text,
1276
1253
  'MimeType': file_description.find(\
1277
1254
  'cdas:MimeType',
1278
- namespaces=NAMESPACES).text,
1255
+ namespaces=NS).text,
1279
1256
  'StartTime': file_description.find(\
1280
1257
  'cdas:StartTime',
1281
- namespaces=NAMESPACES).text,
1258
+ namespaces=NS).text,
1282
1259
  'EndTime': file_description.find(\
1283
1260
  'cdas:EndTime',
1284
- namespaces=NAMESPACES).text,
1261
+ namespaces=NS).text,
1285
1262
  'Length': int(file_description.find(\
1286
1263
  'cdas:Length',
1287
- namespaces=NAMESPACES).text),
1264
+ namespaces=NS).text),
1288
1265
  'LastModified': file_description.find(\
1289
1266
  'cdas:LastModified',
1290
- namespaces=NAMESPACES).text
1267
+ namespaces=NS).text
1291
1268
  }
1292
1269
  thumbnail_dict = CdasWs._get_thumbnail_description_dict(\
1293
1270
  file_description)
@@ -1297,7 +1274,7 @@ class CdasWs:
1297
1274
 
1298
1275
  thumbnail_id_elem = file_description.find(\
1299
1276
  'cdas:ThumbnailId',
1300
- namespaces=NAMESPACES)
1277
+ namespaces=NS)
1301
1278
  if thumbnail_id_elem is not None:
1302
1279
  dict_file_description['ThumbnailId'] = \
1303
1280
  thumbnail_id_elem.text
@@ -24,7 +24,7 @@
24
24
  #
25
25
  # NOSA HEADER END
26
26
  #
27
- # Copyright (c) 2019-2024 United States Government as represented by
27
+ # Copyright (c) 2019-2026 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 &copy; 2019-2024 United States Government as represented by the
39
+ Copyright &copy; 2019-2026 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
  """
@@ -350,7 +350,6 @@ class DataRequest(metaclass=ABCMeta): # pylint: disable=too-few-public-methods
350
350
  string XML representation of this object.
351
351
  """
352
352
 
353
- #return ET.tostring(self.xml_element(), encoding="utf-8", method='xml', xml_declaration=True)
354
353
  return ET.tostring(self.xml_element(), encoding="utf-8", method='xml')
355
354
 
356
355
 
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env python3
2
+
3
+ #
4
+ # NOSA HEADER START
5
+ #
6
+ # The contents of this file are subject to the terms of the NASA Open
7
+ # Source Agreement (NOSA), Version 1.3 only (the "Agreement"). You may
8
+ # not use this file except in compliance with the Agreement.
9
+ #
10
+ # You can obtain a copy of the agreement at
11
+ # docs/NASA_Open_Source_Agreement_1.3.txt
12
+ # or
13
+ # https://cdaweb.gsfc.nasa.gov/WebServices/NASA_Open_Source_Agreement_1.3.txt.
14
+ #
15
+ # See the Agreement for the specific language governing permissions
16
+ # and limitations under the Agreement.
17
+ #
18
+ # When distributing Covered Code, include this NOSA HEADER in each
19
+ # file and include the Agreement file at
20
+ # docs/NASA_Open_Source_Agreement_1.3.txt. If applicable, add the
21
+ # following below this NOSA HEADER, with the fields enclosed by
22
+ # brackets "[]" replaced with your own identifying information:
23
+ # Portions Copyright [yyyy] [name of copyright owner]
24
+ #
25
+ # NOSA HEADER END
26
+ #
27
+ # Copyright (c) 2025 United States Government as represented by
28
+ # the National Aeronautics and Space Administration. No copyright is
29
+ # claimed in the United States under Title 17, U.S.Code. All Other
30
+ # Rights Reserved.
31
+ #
32
+
33
+
34
+ """
35
+ Module defines utility functions related to Digital Object Identifiers
36
+ (DOI).<br>
37
+
38
+ Copyright &copy; 2025 United States Government as represented by the
39
+ National Aeronautics and Space Administration. No copyright is claimed in
40
+ the United States under Title 17, U.S.Code. All Other Rights Reserved.
41
+ """
42
+
43
+
44
+ def get_canonical_doi(
45
+ doi: str
46
+ ) -> str:
47
+ """
48
+ Returns a canonical representation (no leading https://doi.org/ and
49
+ lower case) Digital Object Identifier (DOI) value.
50
+
51
+ Parameters
52
+ ----------
53
+ doi
54
+ digital object identifier.
55
+ Returns
56
+ -------
57
+ str
58
+ The canonical DOI value.
59
+ """
60
+ return doi.replace('https://doi.org/', '').lower()
61
+
62
+
63
+ def get_doi_landing_page_url(
64
+ doi: str
65
+ ) -> str:
66
+ """
67
+ Returns a URL to the given Digital Object Identifier's landing
68
+ page (metadata for the DOI).
69
+
70
+ Parameters
71
+ ----------
72
+ doi
73
+ digital object identifier.
74
+ Returns
75
+ -------
76
+ str
77
+ A URL to the DOI's landing page.
78
+ """
79
+
80
+ if not doi.startswith('http'):
81
+ return 'https://doi.org/' + doi
82
+ return doi
83
+
84
+
85
+ def get_doi_badge_url(
86
+ doi: str
87
+ ) -> str:
88
+ """
89
+ Returns a URL to the given Digital Object Identifier's badge.
90
+
91
+ Parameters
92
+ ----------
93
+ doi
94
+ digital object identifier.
95
+ Returns
96
+ -------
97
+ str
98
+ A URL to the DOI's badge.
99
+ """
100
+
101
+ canonical_doi = get_canonical_doi(doi)
102
+
103
+ return 'https://img.shields.io/badge/DOI-' + \
104
+ canonical_doi.replace('-', '--') + '-blue'
105
+
106
+
107
+ def get_doi_hdp_url(
108
+ doi: str
109
+ ) -> str:
110
+ """
111
+ Returns a URL to the given Digital Object Identifier's Heliophysics
112
+ Data Portal (HDP) page.
113
+
114
+ Parameters
115
+ ----------
116
+ doi
117
+ digital object identifier.
118
+ Returns
119
+ -------
120
+ str
121
+ A URL to the DOI's HDP page.
122
+ """
123
+
124
+ canonical_doi = get_canonical_doi(doi)
125
+
126
+ return 'https://heliophysicsdata.gsfc.nasa.gov/WS/hdp/1/Spase/' \
127
+ 'NumericalData;DisplayData?DOI=' + canonical_doi
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdasws
3
- Version: 1.8.11
3
+ Version: 1.8.13
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
@@ -16,6 +16,7 @@ Classifier: Intended Audience :: System Administrators
16
16
  Classifier: License :: OSI Approved :: NASA Open Source Agreement v1.3 (NASA-1.3)
17
17
  Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3
19
20
  Classifier: Topic :: Scientific/Engineering :: Physics
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
22
  Description-Content-Type: text/markdown
@@ -57,6 +58,8 @@ and can return data from any of
57
58
  [pandas.DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)
58
59
  with all source and
59
60
  [ISTP/SPDF](https://spdf.gsfc.nasa.gov/sp_use_of_cdf.html) metadata.
61
+ Note that this package is included in the [HelioCloud](https://heliocloud.org/)
62
+ base image, so there is no need to install it there.
60
63
  Frequently asked questions concerning this library are at
61
64
  [FAQ](https://cdaweb.gsfc.nasa.gov/WebServices/REST/py/FAQ.html).
62
65
  For more general details about the CDAS web services, see
@@ -3,8 +3,10 @@ README.md
3
3
  setup.py
4
4
  cdasws/__init__.py
5
5
  cdasws/__main__.py
6
+ cdasws/cdasws.py
6
7
  cdasws/datarepresentation.py
7
8
  cdasws/datarequest.py
9
+ cdasws/doi.py
8
10
  cdasws/timeinterval.py
9
11
  cdasws.egg-info/PKG-INFO
10
12
  cdasws.egg-info/SOURCES.txt
@@ -13,4 +15,5 @@ cdasws.egg-info/requires.txt
13
15
  cdasws.egg-info/top_level.txt
14
16
  tests/test_cdasws.py
15
17
  tests/test_datarequest.py
18
+ tests/test_doi.py
16
19
  tests/test_timeinterval.py
@@ -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.8.11",
13
+ version="1.8.13",
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",
@@ -40,6 +40,7 @@ setup(
40
40
  "License :: OSI Approved :: NASA Open Source Agreement v1.3 (NASA-1.3)",
41
41
  "Operating System :: OS Independent",
42
42
  "Programming Language :: Python",
43
+ "Programming Language :: Python :: 3",
43
44
  "Topic :: Scientific/Engineering :: Physics",
44
45
  "Topic :: Software Development :: Libraries :: Python Modules"
45
46
  ],
@@ -24,7 +24,7 @@
24
24
  #
25
25
  # NOSA HEADER END
26
26
  #
27
- # Copyright (c) 2019-2024 United States Government as represented by
27
+ # Copyright (c) 2019-2026 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.
@@ -33,7 +33,7 @@
33
33
  """
34
34
  Module for unittest of the CdasWs class.<br>
35
35
 
36
- Copyright &copy; 2019-2024 United States Government as represented by the
36
+ Copyright &copy; 2019-2026 United States Government as represented by the
37
37
  National Aeronautics and Space Administration. No copyright is claimed in
38
38
  the United States under Title 17, U.S.Code. All Other Rights Reserved.
39
39
  """
@@ -47,8 +47,7 @@ from typing import Dict
47
47
  from context import cdasws # pylint: disable=unused-import
48
48
 
49
49
  # pylint: enable=import-error,wrong-import-position
50
- from cdasws import CdasWs
51
- #from cdasws.cdasws import CdasWs
50
+ from cdasws.cdasws import CdasWs
52
51
  from cdasws.timeinterval import TimeInterval
53
52
  from cdasws.datarequest import GraphOptions, ImageFormat, Overplot
54
53
  # pylint: enable=import-error,wrong-import-position
@@ -1407,7 +1406,7 @@ class TestCdasWs(unittest.TestCase):
1407
1406
  doi = '10.48322/541v-1f57'
1408
1407
  result = \
1409
1408
  self._cdas.get_citation(doi)
1410
- self.assertEqual(result, 'Nakamura, R., Torkar, K. M., Jeszenszky, H., &amp; Burch, J. L. (2022). <i>MMS 1 Active Spacecraft Potential Control (ASPOC), Sensors 1 and 2, Level 2 (L2), Survey Mode, 1 s Data</i> [Data set]. NASA Space Physics Data Facility. https://doi.org/10.48322/541V-1F57')
1409
+ self.assertEqual(result, 'Nakamura, R., Torkar, K. M., Jeszenszky, H., &amp; Burch, J. L. (2022). <i>MMS 1 Active Spacecraft Potential Control (ASPOC), Sensors 1 and 2, Level 2 (L2), Survey Mode, 1 s Data</i> [Data set]. Laboratory for Atmospheric and Space Physics; Space Physics Data Facility. https://doi.org/10.48322/541V-1F57')
1411
1410
 
1412
1411
 
1413
1412
  if __name__ == '__main__':
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env python3
2
+
3
+ #
4
+ # NOSA HEADER START
5
+ #
6
+ # The contents of this file are subject to the terms of the NASA Open
7
+ # Source Agreement (NOSA), Version 1.3 only (the "Agreement"). You may
8
+ # not use this file except in compliance with the Agreement.
9
+ #
10
+ # You can obtain a copy of the agreement at
11
+ # docs/NASA_Open_Source_Agreement_1.3.txt
12
+ # or
13
+ # https://cdaweb.gsfc.nasa.gov/WebServices/NASA_Open_Source_Agreement_1.3.txt.
14
+ #
15
+ # See the Agreement for the specific language governing permissions
16
+ # and limitations under the Agreement.
17
+ #
18
+ # When distributing Covered Code, include this NOSA HEADER in each
19
+ # file and include the Agreement file at
20
+ # docs/NASA_Open_Source_Agreement_1.3.txt. If applicable, add the
21
+ # following below this NOSA HEADER, with the fields enclosed by
22
+ # brackets "[]" replaced with your own identifying information:
23
+ # Portions Copyright [yyyy] [name of copyright owner]
24
+ #
25
+ # NOSA HEADER END
26
+ #
27
+ # Copyright (c) 2025 United States Government as represented by
28
+ # the National Aeronautics and Space Administration. No copyright is
29
+ # claimed in the United States under Title 17, U.S.Code. All Other
30
+ # Rights Reserved.
31
+ #
32
+
33
+ """
34
+ Module for unittest of the doi functions.<br>
35
+
36
+ Copyright &copy; 2025 United States Government as represented by the
37
+ National Aeronautics and Space Administration. No copyright is claimed in
38
+ the United States under Title 17, U.S.Code. All Other Rights Reserved.
39
+ """
40
+
41
+ import unittest
42
+ from cdasws.doi import *
43
+
44
+ #from context import cdasws # pylint: disable=unused-import
45
+
46
+
47
+
48
+ class TestTimeInterval(unittest.TestCase):
49
+ """
50
+ Class for unittest of doi module functions.
51
+ """
52
+
53
+ def __init__(self, *args, **kwargs):
54
+ super(TestTimeInterval, self).__init__(*args, **kwargs)
55
+
56
+
57
+ def test_get_canonical_doi(self):
58
+ """
59
+ Test for get_canonical_doi function.
60
+ """
61
+
62
+ self.assertEqual(get_canonical_doi('https://doi.org/ABC/123'), 'abc/123')
63
+ self.assertEqual(get_canonical_doi('XYZ/321'), 'xyz/321')
64
+
65
+
66
+ def test_get_doi_landing_page_url(self):
67
+ """
68
+ Test for get_doi_landing_page_url function.
69
+ """
70
+
71
+ self.assertEqual(get_doi_landing_page_url('https://doi.org/ABC/123'), 'https://doi.org/ABC/123')
72
+ self.assertEqual(get_doi_landing_page_url('ABC/123'), 'https://doi.org/ABC/123')
73
+
74
+
75
+ def test_get_doi_badge_url(self):
76
+ """
77
+ Test for get_doi_badge_url function.
78
+ """
79
+
80
+ self.assertEqual(get_doi_badge_url('https://doi.org/ABC/123'), 'https://img.shields.io/badge/DOI-abc/123-blue')
81
+ self.assertEqual(get_doi_badge_url('XYZ/321'), 'https://img.shields.io/badge/DOI-xyz/321-blue')
82
+ self.assertEqual(get_doi_badge_url('XYZ/123-321'), 'https://img.shields.io/badge/DOI-xyz/123--321-blue')
83
+
84
+
85
+ def test_get_doi_hdp_url(self):
86
+ """
87
+ Test for get_doi_hdp_url function.
88
+ """
89
+
90
+ self.assertEqual(get_doi_hdp_url('https://doi.org/ABC/123'), 'https://heliophysicsdata.gsfc.nasa.gov/WS/hdp/1/Spase/NumericalData;DisplayData?DOI=abc/123')
91
+
92
+
93
+ if __name__ == '__main__':
94
+ unittest.main()
@@ -43,8 +43,7 @@ from datetime import datetime, timezone
43
43
 
44
44
  from context import cdasws # pylint: disable=unused-import
45
45
 
46
- from cdasws import TimeInterval # pylint: disable=import-error
47
- #from cdasws.cdasws import TimeInterval # pylint: disable=import-error
46
+ from cdasws.cdasws import TimeInterval # pylint: disable=import-error
48
47
 
49
48
 
50
49
 
File without changes
File without changes