@@ -162,13 +162,13 @@ def wrapper(*args):
162162def get_handle (msgid ):
163163 h = ffi .cast ("grib_handle*" , msgid )
164164 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 } " )
166166 return h
167167
168168
169169def put_handle (handle ):
170170 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) " )
172172 return int (ffi .cast ("size_t" , handle ))
173173
174174
@@ -752,12 +752,10 @@ def grib_iterator_next(iterid):
752752 lat_p = ffi .new ("double*" )
753753 lon_p = ffi .new ("double*" )
754754 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
757758 return []
758- elif err < 0 :
759- GRIB_CHECK (err )
760- return None
761759 else :
762760 return (lat_p [0 ], lon_p [0 ], value_p [0 ])
763761
@@ -803,8 +801,7 @@ def grib_keys_iterator_next(iterid):
803801 """
804802 kih = get_grib_keys_iterator (iterid )
805803 res = lib .grib_keys_iterator_next (kih )
806- if res < 0 :
807- GRIB_CHECK (res )
804+ # res is 0 or 1
808805 return res
809806
810807
@@ -887,8 +884,7 @@ def codes_bufr_keys_iterator_next(iterid):
887884 """
888885 bki = get_bufr_keys_iterator (iterid )
889886 res = lib .codes_bufr_keys_iterator_next (bki )
890- if res < 0 :
891- GRIB_CHECK (res )
887+ # res is 0 or 1
892888 return res
893889
894890
@@ -1121,23 +1117,29 @@ def codes_bufr_copy_data(msgid_src, msgid_dst):
11211117
11221118
11231119@require (msgid_src = int )
1124- def grib_clone (msgid_src ):
1120+ def grib_clone (msgid_src , headers_only = False ):
11251121 r"""
11261122 @brief Create a copy of a message.
11271123
11281124 Create a copy of a given message (\em msgid_src) resulting in a new
11291125 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
11301128
11311129 \b Examples: \ref grib_clone.py "grib_clone.py"
11321130
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
11351134 @exception CodesInternalError
11361135 """
11371136 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 )
11391141 if h_dest == ffi .NULL :
1140- raise errors .InvalidGribError ("clone failed" )
1142+ raise errors .MessageInvalidError ("clone failed" )
11411143 return put_handle (h_dest )
11421144
11431145
@@ -2381,7 +2383,7 @@ def grib_new_from_message(message):
23812383 message = message .encode (ENC )
23822384 h = lib .grib_handle_new_from_message_copy (ffi .NULL , message , len (message ))
23832385 if h == ffi .NULL :
2384- raise errors .InvalidGribError ("new_from_message failed" )
2386+ raise errors .MessageInvalidError ("new_from_message failed" )
23852387 return put_handle (h )
23862388
23872389
@@ -2555,10 +2557,10 @@ def codes_extract_offsets(filepath, product_kind, is_strict=True):
25552557 """
25562558 @brief Message offset extraction
25572559
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 )
25622564 @exception CodesInternalError
25632565 """
25642566 context = lib .grib_context_get_default ()
@@ -2579,6 +2581,42 @@ def codes_extract_offsets(filepath, product_kind, is_strict=True):
25792581 i += 1
25802582
25812583
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+
25822620# -------------------------------
25832621# EXPERIMENTAL FEATURES
25842622# -------------------------------
0 commit comments