Missing python3 operators overloading?


#1

I’m trying to port my code to Python 3, but it seems some features are still lacking. The following code work fine :

from panda3d.core import LVector3
print LVector3.unitX() / 2

It returns :

LVector3f(0.5, 0, 0)

But in Python3 (or with __future__), I get the following error:

TypeError: unsupported operand type(s) for /: 'panda3d.core.LVector3f' and 'int'

In Python3 you need to overload __truediv__ and __floordiv__ in order to be able to use the ‘/’ operator and when I print the LVector3 dict there is no mention of these methods :

print LVector3.__dict__
    {'getYz': <method 'getYz' of 'panda3d.core.LVector3f' objects>, 'getXy': <method 'getXy' of 'panda3d.core.LVector3f' objects>, 'signedAngleRad': <method 'signedAngleRad' of 'panda3d.core.LVector3f' objects>, 'right': <staticmethod object at 0x10870d8d8>, 'signed_angle_deg': <method 'signed_angle_deg' of 'panda3d.core.LVector3f' objects>, 'up': <staticmethod object at 0x10870d8a0>, 'relative_angle_rad': <method 'relative_angle_rad' of 'panda3d.core.LVector3f' objects>, 'unit_y': <staticmethod object at 0x10870d6e0>, 'unit_x': <staticmethod object at 0x10870d670>, '__radd__': <slot wrapper '__radd__' of 'panda3d.core.LVector3f' objects>, 'down': <staticmethod object at 0x10870d948>, 'unitZ': <staticmethod object at 0x10870d788>, 'zero': <staticmethod object at 0x10870d638>, 'unitX': <staticmethod object at 0x10870d6a8>, '__rsub__': <slot wrapper '__rsub__' of 'panda3d.core.LVector3f' objects>, '__rdiv__': <slot wrapper '__rdiv__' of 'panda3d.core.LVector3f' objects>, '__rmul__': <slot wrapper '__rmul__' of 'panda3d.core.LVector3f' objects>, '__init__': <slot wrapper '__init__' of 'panda3d.core.LVector3f' objects>, '__setattr__': <slot wrapper '__setattr__' of 'panda3d.core.LVector3f' objects>, '__new__': <built-in method __new__ of type object at 0x105ff2960>, 'cross': <method 'cross' of 'panda3d.core.LVector3f' objects>, 'signedAngleDeg': <method 'signedAngleDeg' of 'panda3d.core.LVector3f' objects>, '__deepcopy__': <method '__deepcopy__' of 'panda3d.core.LVector3f' objects>, 'forward': <staticmethod object at 0x10870d910>, 'angleRad': <method 'angleRad' of 'panda3d.core.LVector3f' objects>, 'get_xy': <method 'get_xy' of 'panda3d.core.LVector3f' objects>, '__doc__': '/**\n * This is a three-component vector distance (as opposed to a three-component\n * point, which represents a particular point in space). Some of the methods\n * are slightly different between LPoint3 and LVector3; in particular,\n * subtraction of two points yields a vector, while addition of a vector and a\n * point yields a point.\n */', '__repr__': <slot wrapper '__repr__' of 'panda3d.core.LVector3f' objects>, 'DtoolClassDict': {...}, 'getXz': <method 'getXz' of 'panda3d.core.LVector3f' objects>, 'getClassType': <staticmethod object at 0x10870da60>, '__getattribute__': <slot wrapper '__getattribute__' of 'panda3d.core.LVector3f' objects>, 'back': <staticmethod object at 0x10870d9b8>, 'angle_deg': <method 'angle_deg' of 'panda3d.core.LVector3f' objects>, 'yz': <attribute 'yz' of 'panda3d.core.LVector3f' objects>, 'normalized': <method 'normalized' of 'panda3d.core.LVector3f' objects>, '__add__': <slot wrapper '__add__' of 'panda3d.core.LVector3f' objects>, 'relative_angle_deg': <method 'relative_angle_deg' of 'panda3d.core.LVector3f' objects>, 'signed_angle_rad': <method 'signed_angle_rad' of 'panda3d.core.LVector3f' objects>, 'get_class_type': <staticmethod object at 0x10870da28>, 'unit_z': <staticmethod object at 0x10870d750>, 'relativeAngleRad': <method 'relativeAngleRad' of 'panda3d.core.LVector3f' objects>, 'angleDeg': <method 'angleDeg' of 'panda3d.core.LVector3f' objects>, 'xz': <attribute 'xz' of 'panda3d.core.LVector3f' objects>, '__copy__': <method '__copy__' of 'panda3d.core.LVector3f' objects>, 'left': <staticmethod object at 0x10870d980>, 'rfu': <staticmethod object at 0x10870d9f0>, 'unitY': <staticmethod object at 0x10870d718>, 'project': <method 'project' of 'panda3d.core.LVector3f' objects>, '__delattr__': <slot wrapper '__delattr__' of 'panda3d.core.LVector3f' objects>, '__div__': <slot wrapper '__div__' of 'panda3d.core.LVector3f' objects>, '__mul__': <slot wrapper '__mul__' of 'panda3d.core.LVector3f' objects>, 'angle_rad': <method 'angle_rad' of 'panda3d.core.LVector3f' objects>, '__neg__': <slot wrapper '__neg__' of 'panda3d.core.LVector3f' objects>, 'xy': <attribute 'xy' of 'panda3d.core.LVector3f' objects>, '__sub__': <slot wrapper '__sub__' of 'panda3d.core.LVector3f' objects>, 'get_xz': <method 'get_xz' of 'panda3d.core.LVector3f' objects>, 'get_yz': <method 'get_yz' of 'panda3d.core.LVector3f' objects>, 'relativeAngleDeg': <method 'relativeAngleDeg' of 'panda3d.core.LVector3f' objects>}

Am I missing something ?


#2

It works for me in Python 3.7:

>>> LVector3(1, 2, 3) / 2.0
LVector3f(0.5, 1, 1.5)
>>> LVector3(1, 2, 3) / 2
LVector3f(0.5, 1, 1.5)

Which Python and Panda3D versions are you using to test that?


#3

Default python on Mac :

$ python --version
Python 2.7.10

And Panda3D freshly compiled from the branch release/1.10.x


#4

Rectification: it happens only in python2 with

from __future__ import division

I used the wrong terminal to test with python3, with python3.7 it works fine (and the overloaded operators are indeed in __dict__)


#5

Ah, yeah. It looks like we’re using a compile-time Python version check to switch which division method we are implementing. Please open an issue on GitHub requesting interrogate to support the division future in Python 2.


#6

Done: https://github.com/panda3d/panda3d/issues/529