From 745e08a57333c0902c804e31542d65cee7cf091b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 16 Jul 2018 08:56:59 -0700 Subject: [PATCH 1/7] use npy_isnan(val) instead of val != val --- pandas/_libs/src/util.pxd | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/src/util.pxd b/pandas/_libs/src/util.pxd index 7ce2181f32553..00da0495cbadc 100644 --- a/pandas/_libs/src/util.pxd +++ b/pandas/_libs/src/util.pxd @@ -29,6 +29,11 @@ cdef extern from "numpy/ndarrayobject.h": bint PyArray_IsIntegerScalar(obj) nogil bint PyArray_Check(obj) nogil +cdef extern from "numpy/npy_math.h": + # Note: apparently npy_isnan has better windows-compat than + # the libc.math.isnan implementation + bint npy_isnan(double x) nogil + # -------------------------------------------------------------------- # Type Checking @@ -159,7 +164,7 @@ cdef inline is_array(object o): cdef inline bint _checknull(object val): try: - return val is None or (cpython.PyFloat_Check(val) and val != val) + return val is None or (cpython.PyFloat_Check(val) and npy_isnan(val)) except ValueError: return False From 169a5000f38eaa52f09445724f2f72d8172b3a6e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 16 Jul 2018 18:50:00 -0700 Subject: [PATCH 2/7] Fix remaining compile-time warnings --- pandas/_libs/groupby.pyx | 10 +++---- pandas/_libs/groupby_helper.pxi.in | 24 +++++++-------- pandas/_libs/hashtable.pyx | 1 + pandas/_libs/hashtable_class_helper.pxi.in | 34 +++++++++++----------- pandas/_libs/hashtable_func_helper.pxi.in | 2 +- pandas/_libs/src/datetime/np_datetime.c | 9 ++++++ pandas/_libs/src/parser/tokenizer.c | 6 ++-- pandas/_libs/src/util.pxd | 3 +- 8 files changed, 50 insertions(+), 39 deletions(-) diff --git a/pandas/_libs/groupby.pyx b/pandas/_libs/groupby.pyx index 5e4a431caca00..86429bc19a0f4 100644 --- a/pandas/_libs/groupby.pyx +++ b/pandas/_libs/groupby.pyx @@ -13,7 +13,7 @@ from numpy cimport (ndarray, uint32_t, uint64_t, float32_t, float64_t) -from util cimport numeric, get_nat +from util cimport numeric, get_nat, npy_isnan from algos cimport (swap, TiebreakEnumType, TIEBREAK_AVERAGE, TIEBREAK_MIN, TIEBREAK_MAX, TIEBREAK_FIRST, TIEBREAK_DENSE) @@ -35,7 +35,7 @@ cdef inline float64_t median_linear(float64_t* a, int n) nogil: # count NAs for i in range(n): - if a[i] != a[i]: + if npy_isnan(a[i]): na_count += 1 if na_count: @@ -46,7 +46,7 @@ cdef inline float64_t median_linear(float64_t* a, int n) nogil: j = 0 for i in range(n): - if a[i] == a[i]: + if not npy_isnan(a[i]): tmp[j] = a[i] j += 1 @@ -160,7 +160,7 @@ def group_cumprod_float64(float64_t[:, :] out, continue for j in range(K): val = values[i, j] - if val == val: + if not npy_isnan(val): accum[lab, j] *= val out[i, j] = accum[lab, j] else: @@ -199,7 +199,7 @@ def group_cumsum(numeric[:, :] out, val = values[i, j] if numeric == float32_t or numeric == float64_t: - if val == val: + if not npy_isnan(val): accum[lab, j] += val out[i, j] = accum[lab, j] else: diff --git a/pandas/_libs/groupby_helper.pxi.in b/pandas/_libs/groupby_helper.pxi.in index 0062a6c8d31ab..97c25847cdf30 100644 --- a/pandas/_libs/groupby_helper.pxi.in +++ b/pandas/_libs/groupby_helper.pxi.in @@ -66,7 +66,7 @@ def group_add_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan - if val == val: + if not npy_isnan(val): nobs[lab, j] += 1 sumx[lab, j] += val @@ -112,7 +112,7 @@ def group_prod_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan - if val == val: + if not npy_isnan(val): nobs[lab, j] += 1 prodx[lab, j] *= val @@ -161,7 +161,7 @@ def group_var_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan - if val == val: + if not npy_isnan(val): nobs[lab, j] += 1 oldmean = mean[lab, j] mean[lab, j] += (val - oldmean) / nobs[lab, j] @@ -209,7 +209,7 @@ def group_mean_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, for j in range(K): val = values[i, j] # not nan - if val == val: + if not npy_isnan(val): nobs[lab, j] += 1 sumx[lab, j] += val @@ -260,10 +260,10 @@ def group_ohlc_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, counts[lab] += 1 val = values[i, 0] - if val != val: + if npy_isnan(val): continue - if out[lab, 0] != out[lab, 0]: + if npy_isnan(out[lab, 0]): out[lab, 0] = out[lab, 1] = out[lab, 2] = out[lab, 3] = val else: out[lab, 1] = max(out[lab, 1], val) @@ -340,7 +340,7 @@ def group_last_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan - if val == val and val != {{nan_val}}: + if not npy_isnan(val) and val != {{nan_val}}: nobs[lab, j] += 1 resx[lab, j] = val @@ -396,7 +396,7 @@ def group_nth_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan - if val == val and val != {{nan_val}}: + if not npy_isnan(val) and val != {{nan_val}}: nobs[lab, j] += 1 if nobs[lab, j] == rank: resx[lab, j] = val @@ -651,7 +651,7 @@ def group_max_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, {{if name == 'int64'}} if val != {{nan_val}}: {{else}} - if val == val and val != {{nan_val}}: + if not npy_isnan(val) and val != {{nan_val}}: {{endif}} nobs[lab, j] += 1 if val > maxx[lab, j]: @@ -706,7 +706,7 @@ def group_min_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, {{if name == 'int64'}} if val != {{nan_val}}: {{else}} - if val == val and val != {{nan_val}}: + if not npy_isnan(val) and val != {{nan_val}}: {{endif}} nobs[lab, j] += 1 if val < minx[lab, j]: @@ -754,7 +754,7 @@ def group_cummin_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, out[i, j] = {{nan_val}} else: {{else}} - if val == val: + if not npy_isnan(val): {{endif}} mval = accum[lab, j] if val < mval: @@ -795,7 +795,7 @@ def group_cummax_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, out[i, j] = {{nan_val}} else: {{else}} - if val == val: + if not npy_isnan(val): {{endif}} mval = accum[lab, j] if val > mval: diff --git a/pandas/_libs/hashtable.pyx b/pandas/_libs/hashtable.pyx index b9a72a0c8285f..8b4fb4aaa3667 100644 --- a/pandas/_libs/hashtable.pyx +++ b/pandas/_libs/hashtable.pyx @@ -16,6 +16,7 @@ cnp.import_array() cdef extern from "numpy/npy_math.h": double NAN "NPY_NAN" + bint npy_isnan(double x) nogil from khash cimport ( diff --git a/pandas/_libs/hashtable_class_helper.pxi.in b/pandas/_libs/hashtable_class_helper.pxi.in index ff6570e2106b2..cd2804b5bd9e7 100644 --- a/pandas/_libs/hashtable_class_helper.pxi.in +++ b/pandas/_libs/hashtable_class_helper.pxi.in @@ -389,7 +389,7 @@ cdef class {{name}}HashTable(HashTable): for i in range(n): val = values[i] - if val != val or (use_na_value and val == na_value2): + if npy_isnan(val) or (use_na_value and val == na_value2): labels[i] = na_sentinel continue @@ -528,7 +528,7 @@ cdef class StringHashTable(HashTable): cpdef get_item(self, object val): cdef: khiter_t k - char *v + const char *v v = util.get_c_string(val) k = kh_get_str(self.table, v) @@ -541,7 +541,7 @@ cdef class StringHashTable(HashTable): cdef: khiter_t k int ret = 0 - char *v + const char *v v = util.get_c_string(val) @@ -560,10 +560,10 @@ cdef class StringHashTable(HashTable): int64_t *resbuf = labels.data khiter_t k kh_str_t *table = self.table - char *v - char **vecs + const char *v + const char **vecs - vecs = malloc(n * sizeof(char *)) + vecs = malloc(n * sizeof(char *)) for i in range(n): val = values[i] v = util.get_c_string(val) @@ -589,10 +589,10 @@ cdef class StringHashTable(HashTable): object val ObjectVector uniques khiter_t k - char *v - char **vecs + const char *v + const char **vecs - vecs = malloc(n * sizeof(char *)) + vecs = malloc(n * sizeof(char *)) uindexer = np.empty(n, dtype=np.int64) for i in range(n): val = values[i] @@ -627,12 +627,12 @@ cdef class StringHashTable(HashTable): Py_ssize_t i, n = len(values) int ret = 0 object val - char *v + const char *v khiter_t k int64_t[:] locs = np.empty(n, dtype=np.int64) # these by-definition *must* be strings - vecs = malloc(n * sizeof(char *)) + vecs = malloc(n * sizeof(char *)) for i in range(n): val = values[i] @@ -660,12 +660,12 @@ cdef class StringHashTable(HashTable): Py_ssize_t i, n = len(values) int ret = 0 object val - char *v - char **vecs + const char *v + const char**vecs khiter_t k # these by-definition *must* be strings - vecs = malloc(n * sizeof(char *)) + vecs = malloc(n * sizeof(char *)) for i in range(n): val = values[i] @@ -693,8 +693,8 @@ cdef class StringHashTable(HashTable): Py_ssize_t idx, count = count_prior int ret = 0 object val - char *v - char **vecs + const char *v + const char**vecs khiter_t k bint use_na_value @@ -705,7 +705,7 @@ cdef class StringHashTable(HashTable): # pre-filter out missing # and assign pointers - vecs = malloc(n * sizeof(char *)) + vecs = malloc(n * sizeof(char *)) for i in range(n): val = values[i] diff --git a/pandas/_libs/hashtable_func_helper.pxi.in b/pandas/_libs/hashtable_func_helper.pxi.in index 521e564447c59..1c98596f58b9e 100644 --- a/pandas/_libs/hashtable_func_helper.pxi.in +++ b/pandas/_libs/hashtable_func_helper.pxi.in @@ -271,7 +271,7 @@ def ismember_{{dtype}}({{scalar}}[:] arr, {{scalar}}[:] values, bint hasnans=0): if k != table.n_buckets: result[i] = 1 else: - result[i] = hasnans and val != val + result[i] = hasnans and npy_isnan(val) {{endif}} kh_destroy_{{ttype}}(table) diff --git a/pandas/_libs/src/datetime/np_datetime.c b/pandas/_libs/src/datetime/np_datetime.c index 1ad8c780ba7a4..104ac93381f86 100644 --- a/pandas/_libs/src/datetime/np_datetime.c +++ b/pandas/_libs/src/datetime/np_datetime.c @@ -28,6 +28,15 @@ This file is derived from NumPy 1.7. See NUMPY_LICENSE.txt #define PyInt_AsLong PyLong_AsLong #endif +// Silence "implicit declaration of function" warnings +int convert_datetimestruct_to_datetime(NPY_DATETIMEUNIT base, + const npy_datetimestruct *dts, + npy_datetime *out); +int convert_timedelta_to_timedeltastruct(NPY_DATETIMEUNIT base, + npy_timedelta td, + pandas_timedeltastruct *out); + + const npy_datetimestruct _NS_MIN_DTS = { 1677, 9, 21, 0, 12, 43, 145225, 0, 0}; const npy_datetimestruct _NS_MAX_DTS = { diff --git a/pandas/_libs/src/parser/tokenizer.c b/pandas/_libs/src/parser/tokenizer.c index 25eede6c286dc..a18d12616a802 100644 --- a/pandas/_libs/src/parser/tokenizer.c +++ b/pandas/_libs/src/parser/tokenizer.c @@ -262,7 +262,7 @@ static int make_stream_space(parser_t *self, size_t nbytes) { ("\n\nmake_stream_space: nbytes = %zu. grow_buffer(self->stream...)\n", nbytes)) self->stream = (char *)grow_buffer((void *)self->stream, self->stream_len, - (size_t*)&self->stream_cap, nbytes * 2, + (int64_t*)&self->stream_cap, nbytes * 2, sizeof(char), &status); TRACE( ("make_stream_space: self->stream=%p, self->stream_len = %zu, " @@ -289,7 +289,7 @@ static int make_stream_space(parser_t *self, size_t nbytes) { cap = self->words_cap; self->words = (char **)grow_buffer((void *)self->words, self->words_len, - (size_t*)&self->words_cap, nbytes, + (int64_t*)&self->words_cap, nbytes, sizeof(char *), &status); TRACE( ("make_stream_space: grow_buffer(self->self->words, %zu, %zu, %zu, " @@ -320,7 +320,7 @@ static int make_stream_space(parser_t *self, size_t nbytes) { cap = self->lines_cap; self->line_start = (int64_t *)grow_buffer((void *)self->line_start, self->lines + 1, - (size_t*)&self->lines_cap, nbytes, + (int64_t*)&self->lines_cap, nbytes, sizeof(int64_t), &status); TRACE(( "make_stream_space: grow_buffer(self->line_start, %zu, %zu, %zu, %d)\n", diff --git a/pandas/_libs/src/util.pxd b/pandas/_libs/src/util.pxd index 00da0495cbadc..b9f2c32bd384a 100644 --- a/pandas/_libs/src/util.pxd +++ b/pandas/_libs/src/util.pxd @@ -32,6 +32,7 @@ cdef extern from "numpy/ndarrayobject.h": cdef extern from "numpy/npy_math.h": # Note: apparently npy_isnan has better windows-compat than # the libc.math.isnan implementation + # See discussion: https://github.com/cython/cython/issues/550 bint npy_isnan(double x) nogil # -------------------------------------------------------------------- @@ -75,7 +76,7 @@ cdef extern from "numpy_helper.h": int assign_value_1d(ndarray, Py_ssize_t, object) except -1 cnp.int64_t get_nat() object get_value_1d(ndarray, Py_ssize_t) - char *get_c_string(object) except NULL + const char *get_c_string(object) except NULL object char_to_string(char*) ctypedef fused numeric: From 9f561365fb4877911b6b5f8067575806e0772b9b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Jul 2018 07:58:38 -0700 Subject: [PATCH 3/7] fix 3.5 linux errors --- pandas/_libs/hashtable_class_helper.pxi.in | 14 +++++++------- pandas/_libs/hashtable_func_helper.pxi.in | 5 +++++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pandas/_libs/hashtable_class_helper.pxi.in b/pandas/_libs/hashtable_class_helper.pxi.in index cd2804b5bd9e7..c862876f6105c 100644 --- a/pandas/_libs/hashtable_class_helper.pxi.in +++ b/pandas/_libs/hashtable_class_helper.pxi.in @@ -29,7 +29,7 @@ dtypes = [('Float64', 'float64', 'float64_t'), ctypedef struct {{name}}VectorData: {{arg}} *data - size_t n, m + Py_ssize_t n, m {{endif}} @@ -147,7 +147,7 @@ cdef class StringVector: cdef resize(self): cdef: char **orig_data - size_t i, m + Py_ssize_t i, m m = self.data.m self.data.m = max(self.data.m * 4, _INIT_VEC_CAP) @@ -172,7 +172,7 @@ cdef class StringVector: def to_array(self): cdef: ndarray ao - size_t n + Py_ssize_t n object val ao = np.empty(self.data.n, dtype=np.object) @@ -198,7 +198,7 @@ cdef class ObjectVector: cdef: PyObject **data - size_t n, m + Py_ssize_t n, m ndarray ao bint external_view_exists @@ -281,7 +281,7 @@ cdef class {{name}}HashTable(HashTable): def sizeof(self, deep=False): """ return the size of my table in bytes """ return self.table.n_buckets * (sizeof({{dtype}}_t) + # keys - sizeof(size_t) + # vals + sizeof(Py_ssize_t) + # vals sizeof(uint32_t)) # flags cpdef get_item(self, {{dtype}}_t val): @@ -522,7 +522,7 @@ cdef class StringHashTable(HashTable): def sizeof(self, deep=False): """ return the size of my table in bytes """ return self.table.n_buckets * (sizeof(char *) + # keys - sizeof(size_t) + # vals + sizeof(Py_ssize_t) + # vals sizeof(uint32_t)) # flags cpdef get_item(self, object val): @@ -769,7 +769,7 @@ cdef class PyObjectHashTable(HashTable): def sizeof(self, deep=False): """ return the size of my table in bytes """ return self.table.n_buckets * (sizeof(PyObject *) + # keys - sizeof(size_t) + # vals + sizeof(Py_ssize_t) + # vals sizeof(uint32_t)) # flags cpdef get_item(self, object val): diff --git a/pandas/_libs/hashtable_func_helper.pxi.in b/pandas/_libs/hashtable_func_helper.pxi.in index 1c98596f58b9e..da4e8f1248985 100644 --- a/pandas/_libs/hashtable_func_helper.pxi.in +++ b/pandas/_libs/hashtable_func_helper.pxi.in @@ -271,7 +271,12 @@ def ismember_{{dtype}}({{scalar}}[:] arr, {{scalar}}[:] values, bint hasnans=0): if k != table.n_buckets: result[i] = 1 else: + {{if dtype == 'float64'}} result[i] = hasnans and npy_isnan(val) + {{else}} + result[i] = hasnans and val != val + {{endif}} + {{endif}} kh_destroy_{{ttype}}(table) From 1ad0516d3b037ae3f2f282449bbf110c6cfab7a8 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Jul 2018 08:01:10 -0700 Subject: [PATCH 4/7] fix 3.5 linux errors --- pandas/_libs/hashtable_class_helper.pxi.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/_libs/hashtable_class_helper.pxi.in b/pandas/_libs/hashtable_class_helper.pxi.in index c862876f6105c..ed1034fbfa8e3 100644 --- a/pandas/_libs/hashtable_class_helper.pxi.in +++ b/pandas/_libs/hashtable_class_helper.pxi.in @@ -389,7 +389,11 @@ cdef class {{name}}HashTable(HashTable): for i in range(n): val = values[i] + {{if dtype == 'float64'}} if npy_isnan(val) or (use_na_value and val == na_value2): + {{else}} + if val != val or (use_na_value and val == na_value2): + {{endif}} labels[i] = na_sentinel continue From f23802c88293aaa4486a7ca55b377cc3a9bac006 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Jul 2018 08:11:44 -0700 Subject: [PATCH 5/7] Fix more linux 3.5 errors --- pandas/_libs/groupby_helper.pxi.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pandas/_libs/groupby_helper.pxi.in b/pandas/_libs/groupby_helper.pxi.in index 97c25847cdf30..19ad374f72374 100644 --- a/pandas/_libs/groupby_helper.pxi.in +++ b/pandas/_libs/groupby_helper.pxi.in @@ -340,7 +340,11 @@ def group_last_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan + {{if c_type.startswith('float')}} if not npy_isnan(val) and val != {{nan_val}}: + {{else}} + if val == val and val != {{nan_val}}: + {{endif}} nobs[lab, j] += 1 resx[lab, j] = val @@ -396,7 +400,11 @@ def group_nth_{{name}}(ndarray[{{dest_type2}}, ndim=2] out, val = values[i, j] # not nan + {{if c_type.startswith('float')}} if not npy_isnan(val) and val != {{nan_val}}: + {{else}} + if val == val and val != {{nan_val}}: + {{endif}} nobs[lab, j] += 1 if nobs[lab, j] == rank: resx[lab, j] = val From 99753ed9b82487a8b9f6f3f70bb3f202e289cc96 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Jul 2018 10:13:00 -0700 Subject: [PATCH 6/7] remove npy_isnan from util since it breaks in cpp file --- pandas/_libs/groupby.pyx | 7 ++++++- pandas/_libs/src/util.pxd | 8 +------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pandas/_libs/groupby.pyx b/pandas/_libs/groupby.pyx index 86429bc19a0f4..43acab765d0d3 100644 --- a/pandas/_libs/groupby.pyx +++ b/pandas/_libs/groupby.pyx @@ -12,8 +12,13 @@ from numpy cimport (ndarray, int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t, float32_t, float64_t) +cdef extern from "numpy/npy_math.h": + # Note: apparently npy_isnan has better windows-compat than + # the libc.math.isnan implementation + # See discussion: https://github.com/cython/cython/issues/550 + bint npy_isnan(double x) nogil -from util cimport numeric, get_nat, npy_isnan +from util cimport numeric, get_nat from algos cimport (swap, TiebreakEnumType, TIEBREAK_AVERAGE, TIEBREAK_MIN, TIEBREAK_MAX, TIEBREAK_FIRST, TIEBREAK_DENSE) diff --git a/pandas/_libs/src/util.pxd b/pandas/_libs/src/util.pxd index b9f2c32bd384a..7285bc6399b49 100644 --- a/pandas/_libs/src/util.pxd +++ b/pandas/_libs/src/util.pxd @@ -29,12 +29,6 @@ cdef extern from "numpy/ndarrayobject.h": bint PyArray_IsIntegerScalar(obj) nogil bint PyArray_Check(obj) nogil -cdef extern from "numpy/npy_math.h": - # Note: apparently npy_isnan has better windows-compat than - # the libc.math.isnan implementation - # See discussion: https://github.com/cython/cython/issues/550 - bint npy_isnan(double x) nogil - # -------------------------------------------------------------------- # Type Checking @@ -165,7 +159,7 @@ cdef inline is_array(object o): cdef inline bint _checknull(object val): try: - return val is None or (cpython.PyFloat_Check(val) and npy_isnan(val)) + return val is None or (cpython.PyFloat_Check(val) and val != val) except ValueError: return False From afb28893e8330a41ba3223dfa9bbf4e744f19dfc Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Jul 2018 10:26:02 -0700 Subject: [PATCH 7/7] casting to avoid warnings --- pandas/io/msgpack/_unpacker.pyx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pandas/io/msgpack/_unpacker.pyx b/pandas/io/msgpack/_unpacker.pyx index 04bb330e595dd..7031563fcd37a 100644 --- a/pandas/io/msgpack/_unpacker.pyx +++ b/pandas/io/msgpack/_unpacker.pyx @@ -139,7 +139,7 @@ def unpackb(object packed, object object_hook=None, object list_hook=None, ret = unpack_construct(&ctx, buf, buf_len, &off) if ret == 1: obj = unpack_data(&ctx) - if off < buf_len: + if off < buf_len: raise ExtraData(obj, PyBytes_FromStringAndSize( buf + off, buf_len - off)) return obj @@ -367,9 +367,11 @@ cdef class Unpacker(object): self.buf_tail = tail + _buf_len cdef read_from_file(self): + # Assume self.max_buffer_size - (self.buf_tail - self.buf_head) >= 0 next_bytes = self.file_like_read( min(self.read_size, - self.max_buffer_size - (self.buf_tail - self.buf_head))) + (self.max_buffer_size - + (self.buf_tail - self.buf_head)))) if next_bytes: self.append_buffer(PyBytes_AsString(next_bytes), PyBytes_Size(next_bytes)) @@ -417,7 +419,9 @@ cdef class Unpacker(object): def read_bytes(self, Py_ssize_t nbytes): """Read a specified number of raw bytes from the stream""" cdef size_t nread - nread = min(self.buf_tail - self.buf_head, nbytes) + + # Assume that self.buf_tail - self.buf_head >= 0 + nread = min((self.buf_tail - self.buf_head), nbytes) ret = PyBytes_FromStringAndSize(self.buf + self.buf_head, nread) self.buf_head += nread if len(ret) < nbytes and self.file_like is not None: