diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2018-08-03 20:57:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-03 20:57:37 -0500 |
commit | b5e01bcb668da0413170a886c258e00d2540e752 (patch) | |
tree | a5f6d002c2012cc3f08202f00f046c2c7f0e4c8a /numpy | |
parent | 8eed36af75d0cc002b3e839e828d8892c1f079d5 (diff) | |
parent | e0fb54f5751e93bcb36eccc00681a9afc35e1c37 (diff) | |
download | numpy-b5e01bcb668da0413170a886c258e00d2540e752.tar.gz |
Merge pull request #11535 from eric-wieser/fix-6511
MAINT: Improve memory usage in PEP3118 format parsing
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/_internal.py | 66 | ||||
-rw-r--r-- | numpy/tests/test_ctypeslib.py | 20 |
2 files changed, 53 insertions, 33 deletions
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py index 9990bacf0..1cf89aab0 100644 --- a/numpy/core/_internal.py +++ b/numpy/core/_internal.py @@ -444,46 +444,46 @@ _pep3118_standard_map = { } _pep3118_standard_typechars = ''.join(_pep3118_standard_map.keys()) -def _dtype_from_pep3118(spec): - class Stream(object): - def __init__(self, s): - self.s = s - self.byteorder = '@' +class _Stream(object): + def __init__(self, s): + self.s = s + self.byteorder = '@' - def advance(self, n): - res = self.s[:n] - self.s = self.s[n:] - return res + def advance(self, n): + res = self.s[:n] + self.s = self.s[n:] + return res - def consume(self, c): - if self.s[:len(c)] == c: - self.advance(len(c)) - return True - return False - - def consume_until(self, c): - if callable(c): - i = 0 - while i < len(self.s) and not c(self.s[i]): - i = i + 1 - return self.advance(i) - else: - i = self.s.index(c) - res = self.advance(i) - self.advance(len(c)) - return res + def consume(self, c): + if self.s[:len(c)] == c: + self.advance(len(c)) + return True + return False - @property - def next(self): - return self.s[0] + def consume_until(self, c): + if callable(c): + i = 0 + while i < len(self.s) and not c(self.s[i]): + i = i + 1 + return self.advance(i) + else: + i = self.s.index(c) + res = self.advance(i) + self.advance(len(c)) + return res - def __bool__(self): - return bool(self.s) - __nonzero__ = __bool__ + @property + def next(self): + return self.s[0] - stream = Stream(spec) + def __bool__(self): + return bool(self.s) + __nonzero__ = __bool__ + +def _dtype_from_pep3118(spec): + stream = _Stream(spec) dtype, align = __dtype_from_pep3118(stream, is_subdtype=False) return dtype diff --git a/numpy/tests/test_ctypeslib.py b/numpy/tests/test_ctypeslib.py index 75ce9c8ca..62793a9d6 100644 --- a/numpy/tests/test_ctypeslib.py +++ b/numpy/tests/test_ctypeslib.py @@ -170,3 +170,23 @@ class TestAsArray(object): check(as_array(pointer(c_array), shape=())) check(as_array(pointer(c_array[0]), shape=(2,))) check(as_array(pointer(c_array[0][0]), shape=(2, 3))) + + def test_reference_cycles(self): + # related to gh-6511 + import ctypes + + # create array to work with + # don't use int/long to avoid running into bpo-10746 + N = 100 + a = np.arange(N, dtype=np.short) + + # get pointer to array + pnt = np.ctypeslib.as_ctypes(a) + + with np.testing.assert_no_gc_cycles(): + # decay the array above to a pointer to its first element + newpnt = ctypes.cast(pnt, ctypes.POINTER(ctypes.c_short)) + # and construct an array using this data + b = np.ctypeslib.as_array(newpnt, (N,)) + # now delete both, which should cleanup both objects + del newpnt, b |