Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DeprecationWarning: integer argument expected, got float #79

Closed
jamadden opened this issue Mar 7, 2018 · 6 comments
Closed

DeprecationWarning: integer argument expected, got float #79

jamadden opened this issue Mar 7, 2018 · 6 comments

Comments

@jamadden
Copy link
Member

jamadden commented Mar 7, 2018

Seen during test runs under Python 2

//BTrees/BTrees/_base.py:1502: DeprecationWarning: integer argument expected, got float
  if not unpack("i", pack("i", v))[0] == v: #pragma: no cover
//BTrees/BTrees/_base.py:1521: DeprecationWarning: integer argument expected, got float
  if not unpack("q", pack("q", v))[0] == v: #pragma: no cover
@mgedmin
Copy link
Member

mgedmin commented Mar 7, 2018

I was unable to reproduce with tox -e py27,py27-pure. Did you mean test runs of BTrees itself, or test runs of something else that triggered warnings inside BTrees?

Do you have a full traceback? These can be extracted by converting warnings to errors with some magical PYTHONWARNINGS setting that I always have trouble crafting up. (A blanket PYTHONWARNINGS=error tends to bomb out somewhere early during test runner setup with an irrelevant warning I don't care about that is ordinarily suppressed, and even PYTHONWARNINGS=default,error::DeprecationWarning sometimes isn't sufficiently specific.)

(It would be kind of ironic to see #pragma: no cover on a line that is covered by unit tests, assuming you meant test runs of BTrees itself.)

@jamadden
Copy link
Member Author

jamadden commented Mar 7, 2018

I'm working in a branch to fix #78, and one of the things I did was convert it to use zope.testrunner instead of python setup.py test. That has the benefit of turning on warnings, so this is issued during the standard test run.

I don't have a traceback yet but I'll try to get one.

@jamadden
Copy link
Member Author

jamadden commented Mar 7, 2018

This is in the to_int and to_long functions. The comment above the lines that raise the warnings is # XXX Python 2.6 doesn't truncate, it spews a warning.

@mgedmin
Copy link
Member

mgedmin commented Mar 7, 2018

one of the things I did was convert it to use zope.testrunner instead of python setup.py test. That has the benefit of turning on warnings

D'oh. I don't know why I had the impression that tox already enables deprecation warnings.

@jamadden
Copy link
Member Author

jamadden commented Mar 7, 2018

We're provoking the warning as a side-effect of test cases that ensure we can't put float values in X[LI]BTree objects.

  File "//BTrees/BTrees/tests/common.py", line 1805, in _insertfloatraises
    self._makeOne().insert(1.4)
  File "//BTrees/BTrees/_base.py", line 572, in add
    return self._set(self._to_key(key))[0]
  File "//BTrees/BTrees/_base.py", line 1507, in to_int
    if not int_unpack(int_pack(v))[0] == v: #pragma: no cover
DeprecationWarning: integer argument expected, got float

On Python 3, that immediately raises a struct.error.

Objects of types with __index__ methods are processed successfully on both versions. Python 3 errors on things with just __int__ while Python 2 raises the same warning.

Could we replace the pack/unpack/equality check with something like:

def to_int(v):
   try:
      return pack('i', operator.index(v))
   except struct_error:
      raise TypeError()

That looks to be pretty comparable to what the C code does using PyLong_AsLongLongAndOverflow and raising if there's overflow. operator.index raises if the object doesn't implement __index__ or __index__ doesn't return an int (or long on Py2).

@jamadden
Copy link
Member Author

jamadden commented Mar 7, 2018

All unit tests pass under PyPy, Py36, Py37, Py27, and Py27-pure with that change.

jamadden added a commit that referenced this issue Mar 9, 2018
Fixes #79

Slightly faster on CPython:

$ python -m perf timeit -s 'from struct import Struct; s = Struct("i"); unpack=s.unpack; pack=s.pack' 'unpack(pack(123456))'
.....................
Mean +- std dev: 252 ns +- 12 ns
$ python -m perf timeit -s 'from struct import Struct; s = Struct("i"); from operator import index; pack=s.pack' 'pack(index(123456))'
.....................
Mean +- std dev: 235 ns +- 6 ns

Very slightly faster on PyPy:

python -m perf timeit -s 'from struct import Struct; s = Struct("i"); unpack=s.unpack; pack=s.pack' 'unpack(pack(123456))'
.........
Mean +- std dev: 4.24 ns +- 0.12 ns
$ python -m perf timeit -s 'from struct import Struct; s = Struct("i"); from operator import index; pack=s.pack' 'pack(index(123456))'
.........
Mean +- std dev: 4.19 ns +- 0.10 ns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants