@@ -306,94 +306,6 @@ def _copy_fields(ary):
306306 'formats' : [dt .fields [name ][0 ] for name in dt .names ]}
307307 return array (ary , dtype = copy_dtype , copy = True )
308308
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-
397309def _getfield_is_safe (oldtype , newtype , offset ):
398310 """ Checks safety of getfield for object arrays.
399311
@@ -415,24 +327,23 @@ def _getfield_is_safe(oldtype, newtype, offset):
415327 If the field access is invalid
416328
417329 """
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
422340
423341def _view_is_safe (oldtype , newtype ):
424342 """ Checks safety of a view involving object arrays, for example when
425343 doing::
426344
427345 np.zeros(10, dtype=oldtype).view(newtype)
428346
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-
436347 Parameters
437348 ----------
438349 oldtype : data-type
@@ -452,31 +363,9 @@ def _view_is_safe(oldtype, newtype):
452363 if oldtype == newtype :
453364 return
454365
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
480369
481370# Given a string containing a PEP 3118 format specifier,
482371# construct a Numpy dtype
0 commit comments