@@ -306,94 +306,6 @@ def _copy_fields(ary):
306
306
'formats' : [dt .fields [name ][0 ] for name in dt .names ]}
307
307
return array (ary , dtype = copy_dtype , copy = True )
308
308
309
- def _get_all_field_offsets (dtype , base_offset = 0 ):
310
- """ Returns the types and offsets of all fields in a (possibly structured)
311
- data type, including nested fields and subarrays.
312
-
313
- Parameters
314
- ----------
315
- dtype : data-type
316
- Data type to extract fields from.
317
- base_offset : int, optional
318
- Additional offset to add to all field offsets.
319
-
320
- Returns
321
- -------
322
- fields : list of (data-type, int) pairs
323
- A flat list of (dtype, byte offset) pairs.
324
-
325
- """
326
- fields = []
327
- if dtype .fields is not None :
328
- for name in dtype .names :
329
- sub_dtype = dtype .fields [name ][0 ]
330
- sub_offset = dtype .fields [name ][1 ] + base_offset
331
- fields .extend (_get_all_field_offsets (sub_dtype , sub_offset ))
332
- else :
333
- if dtype .shape :
334
- sub_offsets = _get_all_field_offsets (dtype .base , base_offset )
335
- count = 1
336
- for dim in dtype .shape :
337
- count *= dim
338
- fields .extend ((typ , off + dtype .base .itemsize * j )
339
- for j in range (count ) for (typ , off ) in sub_offsets )
340
- else :
341
- fields .append ((dtype , base_offset ))
342
- return fields
343
-
344
- def _check_field_overlap (new_fields , old_fields ):
345
- """ Perform object memory overlap tests for two data-types (see
346
- _view_is_safe).
347
-
348
- This function checks that new fields only access memory contained in old
349
- fields, and that non-object fields are not interpreted as objects and vice
350
- versa.
351
-
352
- Parameters
353
- ----------
354
- new_fields : list of (data-type, int) pairs
355
- Flat list of (dtype, byte offset) pairs for the new data type, as
356
- returned by _get_all_field_offsets.
357
- old_fields: list of (data-type, int) pairs
358
- Flat list of (dtype, byte offset) pairs for the old data type, as
359
- returned by _get_all_field_offsets.
360
-
361
- Raises
362
- ------
363
- TypeError
364
- If the new fields are incompatible with the old fields
365
-
366
- """
367
-
368
- #first go byte by byte and check we do not access bytes not in old_fields
369
- new_bytes = set ()
370
- for tp , off in new_fields :
371
- new_bytes .update (set (range (off , off + tp .itemsize )))
372
- old_bytes = set ()
373
- for tp , off in old_fields :
374
- old_bytes .update (set (range (off , off + tp .itemsize )))
375
- if new_bytes .difference (old_bytes ):
376
- raise TypeError ("view would access data parent array doesn't own" )
377
-
378
- #next check that we do not interpret non-Objects as Objects, and vv
379
- obj_offsets = [off for (tp , off ) in old_fields if tp .type is object_ ]
380
- obj_size = dtype (object_ ).itemsize
381
-
382
- for fld_dtype , fld_offset in new_fields :
383
- if fld_dtype .type is object_ :
384
- # check we do not create object views where
385
- # there are no objects.
386
- if fld_offset not in obj_offsets :
387
- raise TypeError ("cannot view non-Object data as Object type" )
388
- else :
389
- # next check we do not create non-object views
390
- # where there are already objects.
391
- # see validate_object_field_overlap for a similar computation.
392
- for obj_offset in obj_offsets :
393
- if (fld_offset < obj_offset + obj_size and
394
- obj_offset < fld_offset + fld_dtype .itemsize ):
395
- raise TypeError ("cannot view Object as non-Object type" )
396
-
397
309
def _getfield_is_safe (oldtype , newtype , offset ):
398
310
""" Checks safety of getfield for object arrays.
399
311
@@ -415,24 +327,23 @@ def _getfield_is_safe(oldtype, newtype, offset):
415
327
If the field access is invalid
416
328
417
329
"""
418
- new_fields = _get_all_field_offsets (newtype , offset )
419
- old_fields = _get_all_field_offsets (oldtype )
420
- # raises if there is a problem
421
- _check_field_overlap (new_fields , old_fields )
330
+ if newtype .hasobject or oldtype .hasobject :
331
+ if offset == 0 and newtype == oldtype :
332
+ return
333
+ if oldtype .names :
334
+ for name in oldtype .names :
335
+ if (oldtype .fields [name ][1 ] == offset and
336
+ oldtype .fields [name ][0 ] == newtype ):
337
+ return
338
+ raise TypeError ("Cannot get/set field of an object array" )
339
+ return
422
340
423
341
def _view_is_safe (oldtype , newtype ):
424
342
""" Checks safety of a view involving object arrays, for example when
425
343
doing::
426
344
427
345
np.zeros(10, dtype=oldtype).view(newtype)
428
346
429
- We need to check that
430
- 1) No memory that is not an object will be interpreted as a object,
431
- 2) No memory containing an object will be interpreted as an arbitrary type.
432
- Both cases can cause segfaults, eg in the case the view is written to.
433
- Strategy here is to also disallow views where newtype has any field in a
434
- place oldtype doesn't.
435
-
436
347
Parameters
437
348
----------
438
349
oldtype : data-type
@@ -452,31 +363,9 @@ def _view_is_safe(oldtype, newtype):
452
363
if oldtype == newtype :
453
364
return
454
365
455
- new_fields = _get_all_field_offsets (newtype )
456
- new_size = newtype .itemsize
457
-
458
- old_fields = _get_all_field_offsets (oldtype )
459
- old_size = oldtype .itemsize
460
-
461
- # if the itemsizes are not equal, we need to check that all the
462
- # 'tiled positions' of the object match up. Here, we allow
463
- # for arbirary itemsizes (even those possibly disallowed
464
- # due to stride/data length issues).
465
- if old_size == new_size :
466
- new_num = old_num = 1
467
- else :
468
- gcd_new_old = _gcd (new_size , old_size )
469
- new_num = old_size // gcd_new_old
470
- old_num = new_size // gcd_new_old
471
-
472
- # get position of fields within the tiling
473
- new_fieldtile = [(tp , off + new_size * j )
474
- for j in range (new_num ) for (tp , off ) in new_fields ]
475
- old_fieldtile = [(tp , off + old_size * j )
476
- for j in range (old_num ) for (tp , off ) in old_fields ]
477
-
478
- # raises if there is a problem
479
- _check_field_overlap (new_fieldtile , old_fieldtile )
366
+ if newtype .hasobject or oldtype .hasobject :
367
+ raise TypeError ("Cannot change data-type for object array." )
368
+ return
480
369
481
370
# Given a string containing a PEP 3118 format specifier,
482
371
# construct a Numpy dtype
0 commit comments