@@ -151,8 +151,47 @@ def _maybe_panel(textgen, title: str, rich: bool):
151151 return title + ":\n " + text
152152
153153
154- def find_set_bits (mask , value , repeated_masks ):
155- bitpos = np .arange (8 )[::- 1 ]
154+ def _get_bit_length (dtype ):
155+ # Check if dtype is a numpy dtype, if not, convert it
156+ if not isinstance (dtype , np .dtype ):
157+ dtype = np .dtype (dtype )
158+
159+ # Calculate the bit length
160+ bit_length = 8 * dtype .itemsize
161+
162+ return bit_length
163+
164+
165+ def _unpackbits (mask , bit_length ):
166+ # Ensure the array is a numpy array
167+ arr = np .asarray (mask )
168+
169+ # Create an output array of the appropriate shape
170+ output_shape = arr .shape + (bit_length ,)
171+ output = np .zeros (output_shape , dtype = np .uint8 )
172+
173+ # Unpack bits
174+ for i in range (bit_length ):
175+ output [..., i ] = (arr >> i ) & 1
176+
177+ return output [..., ::- 1 ]
178+
179+
180+ def _max_chars_for_bit_length (bit_length ):
181+ """
182+ Find the maximum characters needed for a fixed-width display
183+ for integer values of a certain bit_length. Use calculation
184+ for signed integers, since it conservatively will always have
185+ enough characters for signed or unsigned.
186+ """
187+ # Maximum value for signed integers of this bit length
188+ max_val = 2 ** (bit_length - 1 ) - 1
189+ # Add 1 for the negative sign
190+ return len (str (max_val )) + 1
191+
192+
193+ def find_set_bits (mask , value , repeated_masks , bit_length ):
194+ bitpos = np .arange (bit_length )[::- 1 ]
156195 if mask not in repeated_masks :
157196 if value == 0 :
158197 return [- 1 ]
@@ -161,8 +200,8 @@ def find_set_bits(mask, value, repeated_masks):
161200 else :
162201 return [int (np .log2 (mask ))]
163202 else :
164- allset = bitpos [np . unpackbits ( np . uint8 ( mask ) ) == 1 ]
165- setbits = bitpos [np . unpackbits ( np . uint8 ( mask & value ) ) == 1 ]
203+ allset = bitpos [_unpackbits ( mask , bit_length ) == 1 ]
204+ setbits = bitpos [_unpackbits ( mask & value , bit_length ) == 1 ]
166205 return [b if abs (b ) in setbits else - b for b in allset ]
167206
168207
@@ -184,25 +223,30 @@ def _format_flags(accessor, rich):
184223 # for f, (m, _) in flag_dict.items()
185224 # if m is not None and m not in repeated_masks
186225 # ]
226+
227+ bit_length = _get_bit_length (accessor ._obj .dtype )
228+ mask_width = _max_chars_for_bit_length (bit_length )
229+ key_width = max (len (key ) for key in flag_dict )
230+
187231 bit_text = []
188232 value_text = []
189233 for key , (mask , value ) in flag_dict .items ():
190234 if mask is None :
191235 bit_text .append ("✗" if rich else "" )
192236 value_text .append (str (value ))
193237 continue
194- bits = find_set_bits (mask , value , repeated_masks )
195- bitstring = ["." ] * 8
238+ bits = find_set_bits (mask , value , repeated_masks , bit_length )
239+ bitstring = ["." ] * bit_length
196240 if bits == [- 1 ]:
197241 continue
198242 else :
199243 for b in bits :
200244 bitstring [abs (b )] = _format_cf_name ("1" if b >= 0 else "0" , rich )
201245 text = "" .join (bitstring [::- 1 ])
202246 value_text .append (
203- f"{ mask } & { value } "
247+ f"{ mask :{ mask_width } } & { value } "
204248 if key in excl_flags and value is not None
205- else str ( mask )
249+ else f" { mask :{ mask_width } } "
206250 )
207251 bit_text .append (text if rich else f" / Bit: { text } " )
208252
@@ -230,7 +274,9 @@ def _format_flags(accessor, rich):
230274 else :
231275 rows = []
232276 for val , bit , key in zip (value_text , bit_text , flag_dict ):
233- rows .append (f"{ TAB } { _format_cf_name (key , rich )} : { TAB } { val } { bit } " )
277+ rows .append (
278+ f"{ TAB } { _format_cf_name (key , rich ):>{key_width }} : { TAB } { val } { bit } "
279+ )
234280 return _print_rows ("Flag Meanings" , rows , rich )
235281
236282
0 commit comments