Updates - January 2024 ()

* Add bz2

* Support 'b' prefix on str

* List.index() throws an exception if item not found

This is consistent with Python. Added find() method that returns -1 similar to str (although this does not exist in Python's list).

* Update complex64 str and repr

* Fix tests

* Add 'default' arg to min() and max()
pull/536/head
A. R. Shajii 2024-01-19 11:22:20 -05:00 committed by GitHub
parent d23c8c7a75
commit c8bc944a50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 563 additions and 35 deletions

View File

@ -205,13 +205,14 @@ struct Reduction {
break;
case Kind::MIN:
case Kind::MAX: {
// signature is (tuple of args, key, default)
auto name = (kind == Kind::MIN ? "min" : "max");
auto *tup = util::makeTuple({lhs, arg});
auto *none = (*M->getNoneType())();
auto *fn = M->getOrRealizeFunc(name, {tup->getType(), none->getType()}, {},
builtinModule);
auto *fn = M->getOrRealizeFunc(
name, {tup->getType(), none->getType(), none->getType()}, {}, builtinModule);
seqassertn(fn, "{} function not found", name);
result = util::call(fn, {tup, none});
result = util::call(fn, {tup, none, none});
break;
}
default:
@ -452,8 +453,8 @@ struct ReductionIdentifier : public util::Operator {
if (!util::isCallOf(item, rf.name, {type, type}, type, /*method=*/true))
continue;
} else {
if (!util::isCallOf(item, rf.name, {M->getTupleType({type, type}), noneType},
type,
if (!util::isCallOf(item, rf.name,
{M->getTupleType({type, type}), noneType, noneType}, type,
/*method=*/false))
continue;
}

6
stdlib/bz2.codon 100644
View File

@ -0,0 +1,6 @@
# Copyright (C) 2022-2023 Exaloop Inc. <https://exaloop.io>
from internal.file import bzFile
def open(path: str, mode: str = "r") -> bzFile:
return bzFile(path, mode)

View File

@ -71,14 +71,14 @@ class Dict:
yield (self.keys[i], self.values[i])
def __contains__(self, key: K) -> bool:
return self.keys.index(key) != -1
return self.keys.find(key) != -1
def __getitem__(self, key: K) -> V:
i = self.keys.index(key)
i = self.keys.find(key)
return self.values[i]
def __setitem__(self, key: K, val: V):
i = self.keys.index(key)
i = self.keys.find(key)
if i != -1:
self.values[i] = val
else:

View File

@ -39,9 +39,11 @@ class __internal__:
def print(*args):
print(*args, flush=True, file=_C.seq_stdout())
def min(*args, key=None):
def min(*args, key=None, default=None):
if staticlen(args) == 0:
compile_error("min expected at least 1 argument, got 0")
compile_error("min() expected at least 1 argument, got 0")
elif staticlen(args) > 1 and default is not None:
compile_error("min() 'default' argument only allowed for iterables")
elif staticlen(args) == 1:
x = args[0].__iter__()
if not x.done():
@ -58,7 +60,10 @@ def min(*args, key=None):
return s
else:
x.destroy()
raise ValueError("min() arg is an empty sequence")
if default is None:
raise ValueError("min() arg is an empty sequence")
else:
return default
elif staticlen(args) == 2:
a, b = args
if key is None:
@ -76,9 +81,11 @@ def min(*args, key=None):
m = i
return m
def max(*args, key=None):
def max(*args, key=None, default=None):
if staticlen(args) == 0:
compile_error("max expected at least 1 argument, got 0")
compile_error("max() expected at least 1 argument, got 0")
elif staticlen(args) > 1 and default is not None:
compile_error("max() 'default' argument only allowed for iterables")
elif staticlen(args) == 1:
x = args[0].__iter__()
if not x.done():
@ -95,7 +102,10 @@ def max(*args, key=None):
return s
else:
x.destroy()
raise ValueError("max() arg is an empty sequence")
if default is None:
raise ValueError("max() arg is an empty sequence")
else:
return default
elif staticlen(args) == 2:
a, b = args
if key is None:

View File

@ -708,6 +708,37 @@ def gzseek(a: cobj, b: int, c: i32) -> int:
def gzflush(a: cobj, b: i32) -> i32:
pass
# <bzlib.h>
@nocapture
@C
def BZ2_bzopen(a: cobj, b: cobj) -> cobj:
pass
@nocapture
@C
def BZ2_bzread(a: cobj, b: cobj, c: i32) -> i32:
pass
@nocapture
@C
def BZ2_bzwrite(a: cobj, b: cobj, c: i32) -> i32:
pass
@nocapture
@C
def BZ2_bzflush(a: cobj) -> i32:
pass
@nocapture
@C
def BZ2_bzclose(a: cobj) -> None:
pass
@nocapture
@C
def BZ2_bzerror(a: cobj, b: Ptr[i32]) -> cobj:
pass
# <string.h>
@pure
@C

View File

@ -245,12 +245,162 @@ class gzFile:
self.buf = cobj()
self.sz = 0
def _bz_errcheck(stream: cobj):
errnum = i32(0)
msg = _C.BZ2_bzerror(stream, __ptr__(errnum))
if errnum < i32(0):
raise IOError(f"bzip2 error: {str(msg, _C.strlen(msg))}")
class bzFile:
sz: int
buf: Ptr[byte]
fp: cobj
def __init__(self, fp: cobj):
self.fp = fp
self._reset()
def __init__(self, path: str, mode: str):
self.fp = _C.BZ2_bzopen(path.c_str(), mode.c_str())
if not self.fp:
raise IOError(f"file {path} could not be opened")
self._reset()
def _getline(self) -> int:
if not self.buf:
self.sz = 128
self.buf = Ptr[byte](self.sz)
offset = 0
while True:
m = self._gets(self.buf + offset, self.sz - offset)
if m == 0:
if offset == 0:
return -1
break
elif m < 0:
_bz_errcheck(self.fp)
if offset == 0:
return -1
break
offset += m
if self.buf[offset - 1] == byte(10): # '\n'
break
oldsz = self.sz
self.sz *= 2
self.buf = realloc(self.buf, self.sz, oldsz)
return offset
def __iter__(self) -> Generator[str]:
for a in self._iter():
yield a.__ptrcopy__()
def __enter__(self):
pass
def __exit__(self):
self.close()
def close(self):
if self.fp:
_C.BZ2_bzclose(self.fp)
self.fp = cobj()
if self.buf:
free(self.buf)
self._reset()
def readlines(self) -> List[str]:
return [l for l in self]
def write(self, s: str):
self._ensure_open()
_C.BZ2_bzwrite(self.fp, s.ptr, i32(len(s)))
_bz_errcheck(self.fp)
def __file_write_gen__(self, g: Generator[T], T: type):
for s in g:
self.write(str(s))
def read(self, sz: int = -1) -> str:
self._ensure_open()
if sz < 0:
buf = _strbuf()
for a in self._iter():
buf.append(a)
return buf.__str__()
buf = Ptr[byte](sz)
ret = _C.BZ2_bzread(self.fp, buf, i32(sz))
_bz_errcheck(self.fp)
return str(buf, int(ret))
def flush(self):
self._ensure_open()
_C.BZ2_bzflush(self.fp)
_bz_errcheck(self.fp)
def _iter(self) -> Generator[str]:
self._ensure_open()
while True:
rd = self._getline()
if rd != -1:
yield str(self.buf, rd)
else:
break
def _iter_trim_newline(self) -> Generator[str]:
self._ensure_open()
while True:
rd = self._getline()
if rd != -1:
if self.buf[rd - 1] == byte(10):
rd -= 1
yield str(self.buf, rd)
else:
break
def _ensure_open(self):
if not self.fp:
raise IOError("I/O operation on closed file")
def _reset(self):
self.buf = cobj()
self.sz = 0
def _gets(self, buf: cobj, sz: int):
if sz <= 0:
return 0
fp = self.fp
b = byte(0)
i = 0
while i < sz - 1:
status = _C.BZ2_bzread(fp, __ptr__(b), i32(1))
if status == i32(0):
break
elif status < i32(0):
return -1
buf[i] = b
i += 1
if b == byte(10):
break
return i
def open(path: str, mode: str = "r") -> File:
return File(path, mode)
def gzopen(path: str, mode: str = "r") -> gzFile:
return gzFile(path, mode)
def bzopen(path: str, mode: str = "r") -> gzFile:
return bzFile(path, mode)
def is_binary(path: str) -> bool:
# https://stackoverflow.com/questions/898669/how-can-i-detect-if-a-file-is-binary-non-text-in-python/7392391#7392391
# Can get both false positive and false negatives, but still is a

View File

@ -333,6 +333,14 @@ class List:
self.len = 0
def index(self, x: T) -> int:
i = 0
for a in self:
if a == x:
return i
i += 1
raise ValueError(f"{x} is not in list")
def find(self, x: T) -> int:
i = 0
for a in self:
if a == x:

View File

@ -499,7 +499,7 @@ class complex64:
phase += other.imag * log(vabs)
return complex64(len * cos(phase), len * sin(phase))
def __repr__(self) -> str:
def _str(self, include_type: bool) -> str:
@pure
@llvm
def copysign(x: f32, y: f32) -> f32:
@ -515,14 +515,27 @@ class complex64:
ret float %y
if self.real == f32(0.0) and copysign(f32(1.0), self.real) == f32(1.0):
return f"complex64({self.imag}j)"
if include_type:
return f"complex64({self.imag}j)"
else:
return f"{self.imag}j"
else:
sign = "+"
if self.imag < f32(0.0) or (
self.imag == f32(0.0) and copysign(f32(1.0), self.imag) == f32(-1.0)
):
sign = "-"
return f"complex64({self.real}{sign}{fabs(self.imag)}j)"
if include_type:
return f"complex64({self.real}{sign}{fabs(self.imag)}j)"
else:
return f"({self.real}{sign}{fabs(self.imag)}j)"
def __repr__(self) -> str:
return self._str(include_type=True)
def __str__(self) -> str:
return self._str(include_type=False)
def conjugate(self) -> complex64:
return complex64(self.real, -self.imag)

View File

@ -146,3 +146,7 @@ class str:
str.memcpy(p + n, i.ptr, i.len)
n += i.len
return str(p, total)
def __prefix_b__(s: str, N: Static[int]):
# Currently a no-op, as Codon str's are just bytes
return s

View File

@ -4,6 +4,218 @@
def test_min_max():
neg = lambda x: -x
assert min(42, 24) == 24
assert max(42, 24) == 42
assert min([42, 24]) == 24
assert max([42, 24]) == 42
assert min(1, 2, 3, 2, 1, 0, -1, 1, 2) == -1
assert max(1, 2, 3, 2, 1, 0, -1, 1, 2) == 3
assert min([1, 2, 3, 2, 1, 0, -1, 1, 2]) == -1
assert max([1, 2, 3, 2, 1, 0, -1, 1, 2]) == 3
assert min(42, 24, key=neg) == 42
assert max(42, 24, key=neg) == 24
assert min([42, 24], key=neg) == 42
assert max([42, 24], key=neg) == 24
assert min(1, 2, 3, 2, 1, 0, -1, 1, 2, key=neg) == 3
assert max(1, 2, 3, 2, 1, 0, -1, 1, 2, key=neg) == -1
assert min([1, 2, 3, 2, 1, 0, -1, 1, 2], key=neg) == 3
assert max([1, 2, 3, 2, 1, 0, -1, 1, 2], key=neg) == -1
assert min([42, 24], default=100) == 24
assert max([42, 24], default=100) == 42
assert min([1, 2, 3, 2, 1, 0, -1, 1, 2], default=100) == -1
assert max([1, 2, 3, 2, 1, 0, -1, 1, 2], default=100) == 3
assert min([42, 24], default=100, key=neg) == 42
assert max([42, 24], default=100, key=neg) == 24
assert min([1, 2, 3, 2, 1, 0, -1, 1, 2], default=100, key=neg) == 3
assert max([1, 2, 3, 2, 1, 0, -1, 1, 2], default=100, key=neg) == -1
assert max([2, 1, 1, 1, 1]) == 2
assert max([1, 2, 1, 1, 1]) == 2
assert max([1, 1, 2, 1, 1]) == 2
assert max([1, 1, 1, 2, 1]) == 2
assert max([1, 1, 1, 1, 2]) == 2
assert max([2, 1, 1, 1]) == 2
assert max([1, 2, 1, 1]) == 2
assert max([1, 1, 2, 1]) == 2
assert max([1, 1, 1, 2]) == 2
assert max([2, 1, 1]) == 2
assert max([1, 2, 1]) == 2
assert max([1, 1, 2]) == 2
assert max([2, 1]) == 2
assert max([1, 2]) == 2
assert max([2, 1, 1, 1, 1], key=neg) == 1
assert max([1, 2, 1, 1, 1], key=neg) == 1
assert max([1, 1, 2, 1, 1], key=neg) == 1
assert max([1, 1, 1, 2, 1], key=neg) == 1
assert max([1, 1, 1, 1, 2], key=neg) == 1
assert max([2, 1, 1, 1], key=neg) == 1
assert max([1, 2, 1, 1], key=neg) == 1
assert max([1, 1, 2, 1], key=neg) == 1
assert max([1, 1, 1, 2], key=neg) == 1
assert max([2, 1, 1], key=neg) == 1
assert max([1, 2, 1], key=neg) == 1
assert max([1, 1, 2], key=neg) == 1
assert max([2, 1], key=neg) == 1
assert max([1, 2], key=neg) == 1
assert min([2, 1, 1, 1, 1]) == 1
assert min([1, 2, 1, 1, 1]) == 1
assert min([1, 1, 2, 1, 1]) == 1
assert min([1, 1, 1, 2, 1]) == 1
assert min([1, 1, 1, 1, 2]) == 1
assert min([2, 1, 1, 1]) == 1
assert min([1, 2, 1, 1]) == 1
assert min([1, 1, 2, 1]) == 1
assert min([1, 1, 1, 2]) == 1
assert min([2, 1, 1]) == 1
assert min([1, 2, 1]) == 1
assert min([1, 1, 2]) == 1
assert min([2, 1]) == 1
assert min([1, 2]) == 1
assert min([2, 1, 1, 1, 1], key=neg) == 2
assert min([1, 2, 1, 1, 1], key=neg) == 2
assert min([1, 1, 2, 1, 1], key=neg) == 2
assert min([1, 1, 1, 2, 1], key=neg) == 2
assert min([1, 1, 1, 1, 2], key=neg) == 2
assert min([2, 1, 1, 1], key=neg) == 2
assert min([1, 2, 1, 1], key=neg) == 2
assert min([1, 1, 2, 1], key=neg) == 2
assert min([1, 1, 1, 2], key=neg) == 2
assert min([2, 1, 1], key=neg) == 2
assert min([1, 2, 1], key=neg) == 2
assert min([1, 1, 2], key=neg) == 2
assert min([2, 1], key=neg) == 2
assert min([1, 2], key=neg) == 2
assert max([0, 1, 1, 1, 1]) == 1
assert max([1, 0, 1, 1, 1]) == 1
assert max([1, 1, 0, 1, 1]) == 1
assert max([1, 1, 1, 0, 1]) == 1
assert max([1, 1, 1, 1, 0]) == 1
assert max([0, 1, 1, 1]) == 1
assert max([1, 0, 1, 1]) == 1
assert max([1, 1, 0, 1]) == 1
assert max([1, 1, 1, 0]) == 1
assert max([0, 1, 1]) == 1
assert max([1, 0, 1]) == 1
assert max([1, 1, 0]) == 1
assert max([0, 1]) == 1
assert max([1, 0]) == 1
assert max([0, 1, 1, 1, 1], key=neg) == 0
assert max([1, 0, 1, 1, 1], key=neg) == 0
assert max([1, 1, 0, 1, 1], key=neg) == 0
assert max([1, 1, 1, 0, 1], key=neg) == 0
assert max([1, 1, 1, 1, 0], key=neg) == 0
assert max([0, 1, 1, 1], key=neg) == 0
assert max([1, 0, 1, 1], key=neg) == 0
assert max([1, 1, 0, 1], key=neg) == 0
assert max([1, 1, 1, 0], key=neg) == 0
assert max([0, 1, 1], key=neg) == 0
assert max([1, 0, 1], key=neg) == 0
assert max([1, 1, 0], key=neg) == 0
assert max([0, 1], key=neg) == 0
assert max([1, 0], key=neg) == 0
assert min([0, 1, 1, 1, 1]) == 0
assert min([1, 0, 1, 1, 1]) == 0
assert min([1, 1, 0, 1, 1]) == 0
assert min([1, 1, 1, 0, 1]) == 0
assert min([1, 1, 1, 1, 0]) == 0
assert min([0, 1, 1, 1]) == 0
assert min([1, 0, 1, 1]) == 0
assert min([1, 1, 0, 1]) == 0
assert min([1, 1, 1, 0]) == 0
assert min([0, 1, 1]) == 0
assert min([1, 0, 1]) == 0
assert min([1, 1, 0]) == 0
assert min([0, 1]) == 0
assert min([1, 0]) == 0
assert min([0, 1, 1, 1, 1], key=neg) == 1
assert min([1, 0, 1, 1, 1], key=neg) == 1
assert min([1, 1, 0, 1, 1], key=neg) == 1
assert min([1, 1, 1, 0, 1], key=neg) == 1
assert min([1, 1, 1, 1, 0], key=neg) == 1
assert min([0, 1, 1, 1], key=neg) == 1
assert min([1, 0, 1, 1], key=neg) == 1
assert min([1, 1, 0, 1], key=neg) == 1
assert min([1, 1, 1, 0], key=neg) == 1
assert min([0, 1, 1], key=neg) == 1
assert min([1, 0, 1], key=neg) == 1
assert min([1, 1, 0], key=neg) == 1
assert min([0, 1], key=neg) == 1
assert min([1, 0], key=neg) == 1
assert min([0, 1, 1, 1, 1], default=99) == 0
assert min([1, 0, 1, 1, 1], default=99) == 0
assert min([1, 1, 0, 1, 1], default=99) == 0
assert min([1, 1, 1, 0, 1], default=99) == 0
assert min([1, 1, 1, 1, 0], default=99) == 0
assert min([0, 1, 1, 1], default=99) == 0
assert min([1, 0, 1, 1], default=99) == 0
assert min([1, 1, 0, 1], default=99) == 0
assert min([1, 1, 1, 0], default=99) == 0
assert min([0, 1, 1], default=99) == 0
assert min([1, 0, 1], default=99) == 0
assert min([1, 1, 0], default=99) == 0
assert min([0, 1], default=99) == 0
assert min([1, 0], default=99) == 0
assert min(List[int](), default=99) == 99
assert min([0, 1, 1, 1, 1], key=neg, default=99) == 1
assert min([1, 0, 1, 1, 1], key=neg, default=99) == 1
assert min([1, 1, 0, 1, 1], key=neg, default=99) == 1
assert min([1, 1, 1, 0, 1], key=neg, default=99) == 1
assert min([1, 1, 1, 1, 0], key=neg, default=99) == 1
assert min([0, 1, 1, 1], key=neg, default=99) == 1
assert min([1, 0, 1, 1], key=neg, default=99) == 1
assert min([1, 1, 0, 1], key=neg, default=99) == 1
assert min([1, 1, 1, 0], key=neg, default=99) == 1
assert min([0, 1, 1], key=neg, default=99) == 1
assert min([1, 0, 1], key=neg, default=99) == 1
assert min([1, 1, 0], key=neg, default=99) == 1
assert min([0, 1], key=neg, default=99) == 1
assert min([1, 0], key=neg, default=99) == 1
assert min(List[int](), key=neg, default=99) == 99
assert max([0, 1, 1, 1, 1], default=99) == 1
assert max([1, 0, 1, 1, 1], default=99) == 1
assert max([1, 1, 0, 1, 1], default=99) == 1
assert max([1, 1, 1, 0, 1], default=99) == 1
assert max([1, 1, 1, 1, 0], default=99) == 1
assert max([0, 1, 1, 1], default=99) == 1
assert max([1, 0, 1, 1], default=99) == 1
assert max([1, 1, 0, 1], default=99) == 1
assert max([1, 1, 1, 0], default=99) == 1
assert max([0, 1, 1], default=99) == 1
assert max([1, 0, 1], default=99) == 1
assert max([1, 1, 0], default=99) == 1
assert max([0, 1], default=99) == 1
assert max([1, 0], default=99) == 1
assert max(List[int](), default=99) == 99
assert max([0, 1, 1, 1, 1], key=neg, default=99) == 0
assert max([1, 0, 1, 1, 1], key=neg, default=99) == 0
assert max([1, 1, 0, 1, 1], key=neg, default=99) == 0
assert max([1, 1, 1, 0, 1], key=neg, default=99) == 0
assert max([1, 1, 1, 1, 0], key=neg, default=99) == 0
assert max([0, 1, 1, 1], key=neg, default=99) == 0
assert max([1, 0, 1, 1], key=neg, default=99) == 0
assert max([1, 1, 0, 1], key=neg, default=99) == 0
assert max([1, 1, 1, 0], key=neg, default=99) == 0
assert max([0, 1, 1], key=neg, default=99) == 0
assert max([1, 0, 1], key=neg, default=99) == 0
assert max([1, 1, 0], key=neg, default=99) == 0
assert max([0, 1], key=neg, default=99) == 0
assert max([1, 0], key=neg, default=99) == 0
assert max(List[int](), key=neg, default=99) == 99
assert max(2, 1, 1, 1, 1) == 2
assert max(1, 2, 1, 1, 1) == 2
assert max(1, 1, 2, 1, 1) == 2
@ -329,6 +541,82 @@ def test_int_format():
k = Int[128](0x7fffffffffffffff)
assert (str(k), bin(k), oct(k), hex(k)) == ('9223372036854775807', '0b111111111111111111111111111111111111111111111111111111111111111', '0o777777777777777777777', '0x7fffffffffffffff')
@test
def test_complex_format():
import math
assert str(complex(1.1, 2.2)) == '(1.1+2.2j)'
assert str(complex(11.0, -22.0)) == '(11-22j)'
assert str(complex(-111.0, 222.0)) == '(-111+222j)'
assert str(complex(-1111.0, -2222.0)) == '(-1111-2222j)'
assert str(complex(1.0, 0.0)) == '(1+0j)'
assert str(complex(0.0, 1.0)) == '1j'
assert str(complex(-0.0, 1.0)) == '(-0+1j)'
assert str(complex(0.0, -1.0)) == '-1j'
assert str(complex(-0.0, -1.0)) == '(-0-1j)'
assert str(complex(0.0, 0.0)) == '0j'
assert str(complex(0.0, -0.0)) == '-0j'
assert str(complex(-0.0, 0.0)) == '(-0+0j)'
assert str(complex(-0.0, -0.0)) == '(-0-0j)'
assert str(complex(math.inf, math.inf)) == '(inf+infj)'
assert str(complex(-math.inf, math.nan)) == '(-inf+nanj)'
assert str(complex(math.nan, -math.inf)) == '(nan-infj)'
assert str(complex(math.nan, math.nan)) == '(nan+nanj)'
assert repr(complex(1.1, 2.2)) == '(1.1+2.2j)'
assert repr(complex(11.0, -22.0)) == '(11-22j)'
assert repr(complex(-111.0, 222.0)) == '(-111+222j)'
assert repr(complex(-1111.0, -2222.0)) == '(-1111-2222j)'
assert repr(complex(1.0, 0.0)) == '(1+0j)'
assert repr(complex(0.0, 1.0)) == '1j'
assert repr(complex(-0.0, 1.0)) == '(-0+1j)'
assert repr(complex(0.0, -1.0)) == '-1j'
assert repr(complex(-0.0, -1.0)) == '(-0-1j)'
assert repr(complex(0.0, 0.0)) == '0j'
assert repr(complex(0.0, -0.0)) == '-0j'
assert repr(complex(-0.0, 0.0)) == '(-0+0j)'
assert repr(complex(-0.0, -0.0)) == '(-0-0j)'
assert repr(complex(math.inf, math.inf)) == '(inf+infj)'
assert repr(complex(-math.inf, math.nan)) == '(-inf+nanj)'
assert repr(complex(math.nan, -math.inf)) == '(nan-infj)'
assert repr(complex(math.nan, math.nan)) == '(nan+nanj)'
assert str(complex64(1.1, 2.2)) == '(1.1+2.2j)'
assert str(complex64(11.0, -22.0)) == '(11-22j)'
assert str(complex64(-111.0, 222.0)) == '(-111+222j)'
assert str(complex64(-1111.0, -2222.0)) == '(-1111-2222j)'
assert str(complex64(1.0, 0.0)) == '(1+0j)'
assert str(complex64(0.0, 1.0)) == '1j'
assert str(complex64(-0.0, 1.0)) == '(-0+1j)'
assert str(complex64(0.0, -1.0)) == '-1j'
assert str(complex64(-0.0, -1.0)) == '(-0-1j)'
assert str(complex64(0.0, 0.0)) == '0j'
assert str(complex64(0.0, -0.0)) == '-0j'
assert str(complex64(-0.0, 0.0)) == '(-0+0j)'
assert str(complex64(-0.0, -0.0)) == '(-0-0j)'
assert str(complex64(math.inf, math.inf)) == '(inf+infj)'
assert str(complex64(-math.inf, math.nan)) == '(-inf+nanj)'
assert str(complex64(math.nan, -math.inf)) == '(nan-infj)'
assert str(complex64(math.nan, math.nan)) == '(nan+nanj)'
assert repr(complex64(1.1, 2.2)) == 'complex64(1.1+2.2j)'
assert repr(complex64(11.0, -22.0)) == 'complex64(11-22j)'
assert repr(complex64(-111.0, 222.0)) == 'complex64(-111+222j)'
assert repr(complex64(-1111.0, -2222.0)) == 'complex64(-1111-2222j)'
assert repr(complex64(1.0, 0.0)) == 'complex64(1+0j)'
assert repr(complex64(0.0, 1.0)) == 'complex64(1j)'
assert repr(complex64(-0.0, 1.0)) == 'complex64(-0+1j)'
assert repr(complex64(0.0, -1.0)) == 'complex64(-1j)'
assert repr(complex64(-0.0, -1.0)) == 'complex64(-0-1j)'
assert repr(complex64(0.0, 0.0)) == 'complex64(0j)'
assert repr(complex64(0.0, -0.0)) == 'complex64(-0j)'
assert repr(complex64(-0.0, 0.0)) == 'complex64(-0+0j)'
assert repr(complex64(-0.0, -0.0)) == 'complex64(-0-0j)'
assert repr(complex64(math.inf, math.inf)) == 'complex64(inf+infj)'
assert repr(complex64(-math.inf, math.nan)) == 'complex64(-inf+nanj)'
assert repr(complex64(math.nan, -math.inf)) == 'complex64(nan-infj)'
assert repr(complex64(math.nan, math.nan)) == 'complex64(nan+nanj)'
class A:
def __len__(self):
return 42
@ -463,7 +751,7 @@ def test_num_from_str():
assert str(e) == "could not convert string to float: ''"
@test
def test_files(open_fn):
def test_files(open_fn, append_allowed: bool = True):
path = 'build/testfile.txt'
f = open_fn(path, 'w')
f.write('hello\nworld\n')
@ -475,21 +763,24 @@ def test_files(open_fn):
with open_fn(path) as f:
assert f.read(3) == 'hel'
assert f.read() == 'lo\nworld\n'
f.seek(0, 0)
assert f.tell() == 0
assert f.read() == 'hello\nworld\n'
if hasattr(f, "seek"):
f.seek(0, 0)
assert f.tell() == 0
assert f.read() == 'hello\nworld\n'
try:
f.tell()
assert False
except IOError:
pass
if hasattr(f, "tell"):
try:
f.tell()
assert False
except IOError:
pass
try:
f.seek(0, 0)
assert False
except IOError:
pass
if hasattr(f, "seek"):
try:
f.seek(0, 0)
assert False
except IOError:
pass
try:
f.flush()
@ -497,10 +788,16 @@ def test_files(open_fn):
except IOError:
pass
f = open_fn(path, 'a')
f.write('goodbye')
f.flush()
f.close()
if append_allowed:
f = open_fn(path, 'a')
f.write('goodbye')
f.flush()
f.close()
else:
f = open_fn(path, 'w')
f.write('hello\nworld\ngoodbye')
f.flush()
f.close()
with open_fn(path) as f:
assert [line for line in f] == ['hello\n', 'world\n', 'goodbye']
@ -513,6 +810,7 @@ test_min_max()
test_map_filter()
test_gen_builtins()
test_int_format()
test_complex_format()
test_reversed()
test_divmod()
test_pow()
@ -520,6 +818,8 @@ test_num_from_str()
test_files(open)
import gzip
test_files(gzip.open)
import bz2
test_files(bz2.open, append_allowed=False)
# Codon-specific

View File

@ -255,6 +255,11 @@ def test_list():
l5 *= 2
assert l5 == [11, 22, 55, 33, 1, 2, 11, 22, 55, 33, 1, 2]
assert l5.index(33) == 3
try:
l5.index(0)
assert False
except ValueError as e:
assert str(e) == '0 is not in list'
l5 *= 0
assert len(l5) == 0