mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #3555 from Snowapril/remove_complex_methods
Remove several special method of complex class
This commit is contained in:
132
Lib/test/test_complex.py
vendored
132
Lib/test/test_complex.py
vendored
@@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
import sys
|
||||
from test import support
|
||||
from test.support import os_helper
|
||||
from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
|
||||
INVALID_UNDERSCORE_LITERALS)
|
||||
|
||||
@@ -12,6 +12,14 @@ INF = float("inf")
|
||||
NAN = float("nan")
|
||||
# These tests ensure that complex math does the right thing
|
||||
|
||||
ZERO_DIVISION = (
|
||||
(1+1j, 0+0j),
|
||||
(1+1j, 0.0),
|
||||
(1+1j, 0),
|
||||
(1.0, 0+0j),
|
||||
(1, 0+0j),
|
||||
)
|
||||
|
||||
class ComplexTest(unittest.TestCase):
|
||||
|
||||
def assertAlmostEqual(self, a, b):
|
||||
@@ -100,20 +108,34 @@ class ComplexTest(unittest.TestCase):
|
||||
self.check_div(complex(random(), random()),
|
||||
complex(random(), random()))
|
||||
|
||||
self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
|
||||
self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
|
||||
|
||||
self.assertAlmostEqual(complex.__truediv__(2+0j, 1+1j), 1-1j)
|
||||
self.assertRaises(ZeroDivisionError, complex.__truediv__, 1+1j, 0+0j)
|
||||
|
||||
for denom_real, denom_imag in [(0, NAN), (NAN, 0), (NAN, NAN)]:
|
||||
z = complex(0, 0) / complex(denom_real, denom_imag)
|
||||
self.assertTrue(isnan(z.real))
|
||||
self.assertTrue(isnan(z.imag))
|
||||
|
||||
def test_truediv_zero_division(self):
|
||||
for a, b in ZERO_DIVISION:
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
a / b
|
||||
|
||||
def test_floordiv(self):
|
||||
self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 1.5+0j)
|
||||
self.assertRaises(TypeError, complex.__floordiv__, 3+0j, 0+0j)
|
||||
with self.assertRaises(TypeError):
|
||||
(1+1j) // (1+0j)
|
||||
with self.assertRaises(TypeError):
|
||||
(1+1j) // 1.0
|
||||
with self.assertRaises(TypeError):
|
||||
(1+1j) // 1
|
||||
with self.assertRaises(TypeError):
|
||||
1.0 // (1+0j)
|
||||
with self.assertRaises(TypeError):
|
||||
1 // (1+0j)
|
||||
|
||||
def test_floordiv_zero_division(self):
|
||||
for a, b in ZERO_DIVISION:
|
||||
with self.assertRaises(TypeError):
|
||||
a // b
|
||||
|
||||
def test_richcompare(self):
|
||||
self.assertIs(complex.__eq__(1+1j, 1<<10000), False)
|
||||
@@ -162,13 +184,32 @@ class ComplexTest(unittest.TestCase):
|
||||
|
||||
def test_mod(self):
|
||||
# % is no longer supported on complex numbers
|
||||
self.assertRaises(TypeError, (1+1j).__mod__, 0+0j)
|
||||
self.assertRaises(TypeError, lambda: (3.33+4.43j) % 0)
|
||||
self.assertRaises(TypeError, (1+1j).__mod__, 4.3j)
|
||||
with self.assertRaises(TypeError):
|
||||
(1+1j) % (1+0j)
|
||||
with self.assertRaises(TypeError):
|
||||
(1+1j) % 1.0
|
||||
with self.assertRaises(TypeError):
|
||||
(1+1j) % 1
|
||||
with self.assertRaises(TypeError):
|
||||
1.0 % (1+0j)
|
||||
with self.assertRaises(TypeError):
|
||||
1 % (1+0j)
|
||||
|
||||
def test_mod_zero_division(self):
|
||||
for a, b in ZERO_DIVISION:
|
||||
with self.assertRaises(TypeError):
|
||||
a % b
|
||||
|
||||
def test_divmod(self):
|
||||
self.assertRaises(TypeError, divmod, 1+1j, 1+0j)
|
||||
self.assertRaises(TypeError, divmod, 1+1j, 0+0j)
|
||||
self.assertRaises(TypeError, divmod, 1+1j, 1.0)
|
||||
self.assertRaises(TypeError, divmod, 1+1j, 1)
|
||||
self.assertRaises(TypeError, divmod, 1.0, 1+0j)
|
||||
self.assertRaises(TypeError, divmod, 1, 1+0j)
|
||||
|
||||
def test_divmod_zero_division(self):
|
||||
for a, b in ZERO_DIVISION:
|
||||
self.assertRaises(TypeError, divmod, a, b)
|
||||
|
||||
def test_pow(self):
|
||||
self.assertAlmostEqual(pow(1+1j, 0+0j), 1.0)
|
||||
@@ -177,6 +218,7 @@ class ComplexTest(unittest.TestCase):
|
||||
self.assertAlmostEqual(pow(1j, -1), 1/1j)
|
||||
self.assertAlmostEqual(pow(1j, 200), 1)
|
||||
self.assertRaises(ValueError, pow, 1+1j, 1+1j, 1+1j)
|
||||
self.assertRaises(OverflowError, pow, 1e200+1j, 1e200+1j)
|
||||
|
||||
a = 3.33+4.43j
|
||||
self.assertEqual(a ** 0j, 1)
|
||||
@@ -209,6 +251,54 @@ class ComplexTest(unittest.TestCase):
|
||||
b = 5.1+2.3j
|
||||
self.assertRaises(ValueError, pow, a, b, 0)
|
||||
|
||||
# Check some boundary conditions; some of these used to invoke
|
||||
# undefined behaviour (https://bugs.python.org/issue44698). We're
|
||||
# not actually checking the results of these operations, just making
|
||||
# sure they don't crash (for example when using clang's
|
||||
# UndefinedBehaviourSanitizer).
|
||||
values = (sys.maxsize, sys.maxsize+1, sys.maxsize-1,
|
||||
-sys.maxsize, -sys.maxsize+1, -sys.maxsize+1)
|
||||
for real in values:
|
||||
for imag in values:
|
||||
with self.subTest(real=real, imag=imag):
|
||||
c = complex(real, imag)
|
||||
try:
|
||||
c ** real
|
||||
except OverflowError:
|
||||
pass
|
||||
try:
|
||||
c ** c
|
||||
except OverflowError:
|
||||
pass
|
||||
|
||||
def test_pow_with_small_integer_exponents(self):
|
||||
# Check that small integer exponents are handled identically
|
||||
# regardless of their type.
|
||||
values = [
|
||||
complex(5.0, 12.0),
|
||||
complex(5.0e100, 12.0e100),
|
||||
complex(-4.0, INF),
|
||||
complex(INF, 0.0),
|
||||
]
|
||||
exponents = [-19, -5, -3, -2, -1, 0, 1, 2, 3, 5, 19]
|
||||
for value in values:
|
||||
for exponent in exponents:
|
||||
with self.subTest(value=value, exponent=exponent):
|
||||
try:
|
||||
int_pow = value**exponent
|
||||
except OverflowError:
|
||||
int_pow = "overflow"
|
||||
try:
|
||||
float_pow = value**float(exponent)
|
||||
except OverflowError:
|
||||
float_pow = "overflow"
|
||||
try:
|
||||
complex_pow = value**complex(exponent)
|
||||
except OverflowError:
|
||||
complex_pow = "overflow"
|
||||
self.assertEqual(str(float_pow), str(int_pow))
|
||||
self.assertEqual(str(complex_pow), str(int_pow))
|
||||
|
||||
def test_boolcontext(self):
|
||||
for i in range(100):
|
||||
self.assertTrue(complex(random() + 1e-6, random() + 1e-6))
|
||||
@@ -509,22 +599,6 @@ class ComplexTest(unittest.TestCase):
|
||||
def test_neg(self):
|
||||
self.assertEqual(-(1+6j), -1-6j)
|
||||
|
||||
def test_file(self):
|
||||
a = 3.33+4.43j
|
||||
b = 5.1+2.3j
|
||||
|
||||
fo = None
|
||||
try:
|
||||
fo = open(os_helper.TESTFN, "w")
|
||||
print(a, b, file=fo)
|
||||
fo.close()
|
||||
fo = open(os_helper.TESTFN, "r")
|
||||
self.assertEqual(fo.read(), ("%s %s\n" % (a, b)))
|
||||
finally:
|
||||
if (fo is not None) and (not fo.closed):
|
||||
fo.close()
|
||||
os_helper.unlink(os_helper.TESTFN)
|
||||
|
||||
def test_getnewargs(self):
|
||||
self.assertEqual((1+2j).__getnewargs__(), (1.0, 2.0))
|
||||
self.assertEqual((1-2j).__getnewargs__(), (1.0, -2.0))
|
||||
@@ -715,8 +789,6 @@ class ComplexTest(unittest.TestCase):
|
||||
self.assertEqual(format(complex(INF, 1), 'F'), 'INF+1.000000j')
|
||||
self.assertEqual(format(complex(INF, -1), 'F'), 'INF-1.000000j')
|
||||
|
||||
def test_main():
|
||||
support.run_unittest(ComplexTest)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
unittest.main()
|
||||
|
||||
@@ -10,7 +10,6 @@ use crate::{
|
||||
use num_complex::Complex64;
|
||||
use num_traits::Zero;
|
||||
use rustpython_common::{float_ops, hash};
|
||||
use std::convert::Infallible as Never;
|
||||
|
||||
/// Create a complex number from a real part and an optional imaginary part.
|
||||
///
|
||||
@@ -272,16 +271,6 @@ impl PyComplex {
|
||||
self.value.conj()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn float(&self, vm: &VirtualMachine) -> PyResult<Never> {
|
||||
Err(vm.new_type_error(String::from("Can't convert complex to float")))
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn int(&self, vm: &VirtualMachine) -> PyResult<Never> {
|
||||
Err(vm.new_type_error(String::from("Can't convert complex to int")))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmul__")]
|
||||
#[pymethod(magic)]
|
||||
fn mul(
|
||||
@@ -310,24 +299,6 @@ impl PyComplex {
|
||||
self.op(other, |a, b| inner_div(b, a, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mod__")]
|
||||
#[pymethod(name = "__rmod__")]
|
||||
fn mod_(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult<Never> {
|
||||
Err(vm.new_type_error("can't mod complex numbers.".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rfloordiv__")]
|
||||
#[pymethod(magic)]
|
||||
fn floordiv(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult<Never> {
|
||||
Err(vm.new_type_error("can't take floor of complex number.".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rdivmod__")]
|
||||
#[pymethod(magic)]
|
||||
fn divmod(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult<Never> {
|
||||
Err(vm.new_type_error("can't take floor or mod of complex number.".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn pos(&self) -> Complex64 {
|
||||
self.value
|
||||
|
||||
Reference in New Issue
Block a user