@@ -162,13 +162,13 @@ def wrapper(*args):
162
162
def get_handle (msgid ):
163
163
h = ffi .cast ("grib_handle*" , msgid )
164
164
if h == ffi .NULL :
165
- raise errors .InvalidGribError (f"get_handle: Bad message ID { msgid } " )
165
+ raise errors .NullHandleError (f"get_handle: Bad message ID { msgid } " )
166
166
return h
167
167
168
168
169
169
def put_handle (handle ):
170
170
if handle == ffi .NULL :
171
- raise errors .InvalidGribError ( f "put_handle: Bad message ID { handle } " )
171
+ raise errors .NullHandleError ( "put_handle: Bad message ID ( handle is NULL) " )
172
172
return int (ffi .cast ("size_t" , handle ))
173
173
174
174
@@ -752,12 +752,10 @@ def grib_iterator_next(iterid):
752
752
lat_p = ffi .new ("double*" )
753
753
lon_p = ffi .new ("double*" )
754
754
value_p = ffi .new ("double*" )
755
- err = lib .grib_iterator_next (iterh , lat_p , lon_p , value_p )
756
- if err == 0 :
755
+ retval = lib .grib_iterator_next (iterh , lat_p , lon_p , value_p )
756
+ if retval == 0 :
757
+ # No more data available. End of iteration
757
758
return []
758
- elif err < 0 :
759
- GRIB_CHECK (err )
760
- return None
761
759
else :
762
760
return (lat_p [0 ], lon_p [0 ], value_p [0 ])
763
761
@@ -803,8 +801,7 @@ def grib_keys_iterator_next(iterid):
803
801
"""
804
802
kih = get_grib_keys_iterator (iterid )
805
803
res = lib .grib_keys_iterator_next (kih )
806
- if res < 0 :
807
- GRIB_CHECK (res )
804
+ # res is 0 or 1
808
805
return res
809
806
810
807
@@ -887,8 +884,7 @@ def codes_bufr_keys_iterator_next(iterid):
887
884
"""
888
885
bki = get_bufr_keys_iterator (iterid )
889
886
res = lib .codes_bufr_keys_iterator_next (bki )
890
- if res < 0 :
891
- GRIB_CHECK (res )
887
+ # res is 0 or 1
892
888
return res
893
889
894
890
@@ -1121,23 +1117,29 @@ def codes_bufr_copy_data(msgid_src, msgid_dst):
1121
1117
1122
1118
1123
1119
@require (msgid_src = int )
1124
- def grib_clone (msgid_src ):
1120
+ def grib_clone (msgid_src , headers_only = False ):
1125
1121
r"""
1126
1122
@brief Create a copy of a message.
1127
1123
1128
1124
Create a copy of a given message (\em msgid_src) resulting in a new
1129
1125
message in memory (\em msgid_dest) identical to the original one.
1126
+ If the headers_only option is enabled, the clone will not contain
1127
+ the Bitmap and Data sections
1130
1128
1131
1129
\b Examples: \ref grib_clone.py "grib_clone.py"
1132
1130
1133
- @param msgid_src id of message to be cloned
1134
- @return id of clone
1131
+ @param msgid_src id of message to be cloned
1132
+ @param headers_only whether or not to clone the message with the headers only
1133
+ @return id of clone
1135
1134
@exception CodesInternalError
1136
1135
"""
1137
1136
h_src = get_handle (msgid_src )
1138
- h_dest = lib .grib_handle_clone (h_src )
1137
+ if headers_only :
1138
+ h_dest = lib .grib_handle_clone_headers_only (h_src )
1139
+ else :
1140
+ h_dest = lib .grib_handle_clone (h_src )
1139
1141
if h_dest == ffi .NULL :
1140
- raise errors .InvalidGribError ("clone failed" )
1142
+ raise errors .MessageInvalidError ("clone failed" )
1141
1143
return put_handle (h_dest )
1142
1144
1143
1145
@@ -2381,7 +2383,7 @@ def grib_new_from_message(message):
2381
2383
message = message .encode (ENC )
2382
2384
h = lib .grib_handle_new_from_message_copy (ffi .NULL , message , len (message ))
2383
2385
if h == ffi .NULL :
2384
- raise errors .InvalidGribError ("new_from_message failed" )
2386
+ raise errors .MessageInvalidError ("new_from_message failed" )
2385
2387
return put_handle (h )
2386
2388
2387
2389
@@ -2555,10 +2557,10 @@ def codes_extract_offsets(filepath, product_kind, is_strict=True):
2555
2557
"""
2556
2558
@brief Message offset extraction
2557
2559
2558
- @param filepath path of input file
2559
- @product_kind one of CODES_PRODUCT_GRIB, CODES_PRODUCT_BUFR, CODES_PRODUCT_ANY or CODES_PRODUCT_GTS
2560
- @param is_strict if True, fail as soon as any invalid message is encountered
2561
- @return a generator that yields offsets (each offset is an integer )
2560
+ @param filepath path of input file
2561
+ @param product_kind one of CODES_PRODUCT_GRIB, CODES_PRODUCT_BUFR, CODES_PRODUCT_ANY or CODES_PRODUCT_GTS
2562
+ @param is_strict if True, fail as soon as any invalid message is encountered
2563
+ @return a generator that yields offsets (as integers )
2562
2564
@exception CodesInternalError
2563
2565
"""
2564
2566
context = lib .grib_context_get_default ()
@@ -2579,6 +2581,42 @@ def codes_extract_offsets(filepath, product_kind, is_strict=True):
2579
2581
i += 1
2580
2582
2581
2583
2584
+ def codes_extract_offsets_sizes (filepath , product_kind , is_strict = True ):
2585
+ """
2586
+ @brief Message offset and size extraction
2587
+
2588
+ @param filepath path of input file
2589
+ @param product_kind one of CODES_PRODUCT_GRIB, CODES_PRODUCT_BUFR, CODES_PRODUCT_ANY or CODES_PRODUCT_GTS
2590
+ @param is_strict if True, fail as soon as any invalid message is encountered
2591
+ @return a generator that yields lists of pairs of offsets and sizes (as integers)
2592
+ @exception CodesInternalError
2593
+ """
2594
+ context = lib .grib_context_get_default ()
2595
+ offsets_p = ffi .new ("long int**" )
2596
+ sizes_p = ffi .new ("size_t**" )
2597
+ num_message_p = ffi .new ("int*" )
2598
+
2599
+ err = lib .codes_extract_offsets_sizes_malloc (
2600
+ context ,
2601
+ filepath .encode (ENC ),
2602
+ product_kind ,
2603
+ offsets_p ,
2604
+ sizes_p ,
2605
+ num_message_p ,
2606
+ is_strict ,
2607
+ )
2608
+ GRIB_CHECK (err )
2609
+
2610
+ num_messages = num_message_p [0 ]
2611
+ offsets = offsets_p [0 ]
2612
+ sizes = sizes_p [0 ]
2613
+
2614
+ i = 0
2615
+ while i < num_messages :
2616
+ yield (offsets [i ], sizes [i ])
2617
+ i += 1
2618
+
2619
+
2582
2620
# -------------------------------
2583
2621
# EXPERIMENTAL FEATURES
2584
2622
# -------------------------------
0 commit comments