@@ -305,14 +305,21 @@ def _extract_recreation_code(value):
305305 else :
306306 return 3 # NoneType
307307
308+ @staticmethod
309+ def _encode_value (value ):
310+ if not isinstance (value , str ):
311+ return value
312+ else :
313+ return value .encode (_encoding )
314+
308315 def __init__ (self , sequence = None , * , name = None ):
309316 if name is None or sequence is not None :
310317 sequence = sequence or ()
311318 _formats = [
312319 self ._types_mapping [type (item )]
313320 if not isinstance (item , (str , bytes ))
314321 else self ._types_mapping [type (item )] % (
315- self ._alignment * (len (item ) // self ._alignment + 1 ),
322+ self ._alignment * (( len (self . _encode_value ( item )) - 1 ) // self ._alignment + 1 ),
316323 )
317324 for item in sequence
318325 ]
@@ -342,31 +349,40 @@ def __init__(self, sequence=None, *, name=None):
342349
343350 if sequence is not None :
344351 _enc = _encoding
345- struct .pack_into (
346- "q" + self ._format_size_metainfo ,
347- self .shm .buf ,
348- 0 ,
349- self ._list_len ,
350- * (self ._allocated_offsets )
351- )
352- struct .pack_into (
353- "" .join (_formats ),
354- self .shm .buf ,
355- self ._offset_data_start ,
356- * (v .encode (_enc ) if isinstance (v , str ) else v for v in sequence )
357- )
358- struct .pack_into (
359- self ._format_packing_metainfo ,
360- self .shm .buf ,
361- self ._offset_packing_formats ,
362- * (v .encode (_enc ) for v in _formats )
363- )
364- struct .pack_into (
365- self ._format_back_transform_codes ,
366- self .shm .buf ,
367- self ._offset_back_transform_codes ,
368- * (_recreation_codes )
369- )
352+ try :
353+ struct .pack_into (
354+ "q" + self ._format_size_metainfo ,
355+ self .shm .buf ,
356+ 0 ,
357+ self ._list_len ,
358+ * (self ._allocated_offsets )
359+ )
360+ struct .pack_into (
361+ "" .join (_formats ),
362+ self .shm .buf ,
363+ self ._offset_data_start ,
364+ * (self ._encode_value (v ) for v in sequence )
365+ )
366+ struct .pack_into (
367+ self ._format_packing_metainfo ,
368+ self .shm .buf ,
369+ self ._offset_packing_formats ,
370+ * (v .encode (_enc ) for v in _formats )
371+ )
372+ struct .pack_into (
373+ self ._format_back_transform_codes ,
374+ self .shm .buf ,
375+ self ._offset_back_transform_codes ,
376+ * (_recreation_codes )
377+ )
378+ except BaseException :
379+ # A value of a supported type may still be unpackable, such as
380+ # an int outside the signed 64-bit range. The block was created
381+ # above and the caller gets no object to release it with, so
382+ # destroy it here.
383+ self .shm .close ()
384+ self .shm .unlink ()
385+ raise
370386
371387 else :
372388 self ._list_len = len (self ) # Obtains size from offset 0 in buffer.
@@ -463,8 +479,7 @@ def __setitem__(self, position, value):
463479 else :
464480 allocated_length = self ._allocated_offsets [position + 1 ] - item_offset
465481
466- encoded_value = (value .encode (_encoding )
467- if isinstance (value , str ) else value )
482+ encoded_value = self ._encode_value (value )
468483 if len (encoded_value ) > allocated_length :
469484 raise ValueError ("bytes/str item exceeds available storage" )
470485 if current_format [- 1 ] == "s" :
0 commit comments