Skip to content

Commit

Permalink
Format 1-element tuples as "(x,)" (#521)
Browse files Browse the repository at this point in the history
* Format 1-element tuples as "(x,)"

Currently, single-element tuple "repr" / "str" gives "(x)", but it should really give "(x,)" according to Python.

* Fix tests
  • Loading branch information
arshajii authored Jan 2, 2024
1 parent f476ff2 commit d609629
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 10 deletions.
10 changes: 10 additions & 0 deletions stdlib/internal/internal.codon
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,16 @@ class __internal__:
return str(buf, total)

def tuple_str(strs: Ptr[str], names: Ptr[str], n: int) -> str:
# special case of 1-element plain tuple: format as "(x,)"
if n == 1 and names[0].len == 0:
total = strs[0].len + 3
buf = Ptr[byte](total)
buf[0] = byte(40) # '('
str.memcpy(buf + 1, strs[0].ptr, strs[0].len)
buf[total - 2] = byte(44) # ','
buf[total - 1] = byte(41) # ')'
return str(buf, total)

total = 2 # one for each of '(' and ')'
i = 0
while i < n:
Expand Down
7 changes: 7 additions & 0 deletions test/core/containers.codon
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ def test_tuple():
assert a[0:] == 3
assert a[0:1] == 42
assert a[:] == -1

assert str((11, 2, 333)) == '(11, 2, 333)'
assert str(()) == '()'
assert str((42,)) == '(42,)'
assert repr((11, 2, 333)) == '(11, 2, 333)'
assert repr(()) == '()'
assert repr((42,)) == '(42,)'
test_tuple()

@test
Expand Down
2 changes: 1 addition & 1 deletion test/parser/simplify_expr.codon
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ t: tuple[int, int] = (1, 2)
print t #: (1, 2)

tt: Tuple[int] = (1, )
print tt #: (1)
print tt #: (1,)

def foo(i: int) -> int:
return i + 1
Expand Down
8 changes: 4 additions & 4 deletions test/parser/typecheck_expr.codon
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ print z[:1], z[1:], z[1:3], z[:4:2], z[::-1] #: [1] [2, 3, 4, 5] [2, 3] [1, 3]
a = (1, '2s', 3.3)
print a[1] #: 2s
print a[0:2], a[:2], a[1:] #: (1, '2s') (1, '2s') ('2s', 3.3)
print a[0:3:2], a[-1:] #: (1, 3.3) (3.3)
print a[0:3:2], a[-1:] #: (1, 3.3) (3.3,)

#%% static_index_side,barebones
def foo(a):
Expand Down Expand Up @@ -470,14 +470,14 @@ p('s', zh=65) #: s () (zh: 65)
q = p(zh=43, ...)
q(1) #: 1 () (zh: 43)
r = q(5, 38, ...)
r() #: 5 (38) (zh: 43)
r() #: 5 (38,) (zh: 43)
r(1, a=1) #: 5 (38, 1) (zh: 43, a: 1)

#%% call_args_kwargs_type,barebones
def foo(*args: float, **kwargs: int):
print(args, kwargs, args.__class__.__name__)

foo(1, f=1) #: (1) (f: 1) Tuple[float]
foo(1, f=1) #: (1,) (f: 1) Tuple[float]
foo(1, 2.1, 3, z=2) #: (1, 2.1, 3) (z: 2) Tuple[float,float,float]

def sum(x: Generator[int]):
Expand Down Expand Up @@ -517,7 +517,7 @@ foo(1, 2, 3)
#: a (1, 2, 3)
#: k (x: 1)
foo(1, 2, 3, 4)
#: 1 2 3 (4) ()
#: 1 2 3 (4,) ()
#: a (1, 2, 4, 3)
#: k (x: 1)
foo(1, 2, zamboni=3)
Expand Down
2 changes: 1 addition & 1 deletion test/parser/typecheck_stmt.codon
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ print foo(N=1, x=2.0) #: 1.41421
print foo(N=1, x=(1, 'bar')) #: foo: bar
print foo(N=1, x=(1, 2)) #: len 2
print foo(N=3, x=(1, 2)) #: ()
print foo(N=1, x=(1, 2, 3)) #: (3)
print foo(N=1, x=(1, 2, 3)) #: (3,)

#%% try_throw,barebones
class MyError(Static[Exception]):
Expand Down
8 changes: 4 additions & 4 deletions test/parser/types.codon
Original file line number Diff line number Diff line change
Expand Up @@ -940,9 +940,9 @@ print zoo(2, 3)
print zoo('s', 3)
#: decorating zoo[...,...,...]
#: decorator (2, 3) ()
#: zoo: 5, 2, (3)
#: zoo: 5, 2, (3,)
#: decorator ('s', 3) ()
#: zoo: 5, s, (3)
#: zoo: 5, s, (3,)

def mydecorator(func):
def inner():
Expand Down Expand Up @@ -1154,13 +1154,13 @@ call(foo)

def foo(a:int, *b: float): return f"{a}_{b}", a+b[0]
call(foo)
#: ('1_(2)', 3)
#: ('1_(2,)', 3)

def call(f: Callable[[int,int],str]):
print(f(1, 2))
def foo(a: int, *b: int, **kw): return f"{a}_{b}_{kw}"
call(foo(zzz=1.1, ...))
#: 1_(2)_(zzz: 1.1)
#: 1_(2,)_(zzz: 1.1)

#%% traits_error,barebones
def t[T](x: T, key: Optional[Callable[[T], S]] = None, S: type = NoneType):
Expand Down

0 comments on commit d609629

Please sign in to comment.