Skip to content

Commit 990c294

Browse files
Merge remote-tracking branch 'origin/master' into joey/fun-with-functions
Conflicts: vm/src/pyobject.rs
2 parents 67f8c02 + 40c1a0f commit 990c294

36 files changed

+905
-259
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/src/lexer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct Lexer<T: Iterator<Item = char>> {
5555
pub enum LexicalError {
5656
StringError,
5757
NestingError,
58+
UnrecognizedToken { tok: char },
5859
}
5960

6061
#[derive(Clone, Debug, Default, PartialEq)]
@@ -687,7 +688,9 @@ where
687688

688689
match self.chr0 {
689690
Some('0'..='9') => return Some(self.lex_number()),
690-
Some('_') | Some('a'..='z') | Some('A'..='Z') => return Some(self.lex_identifier()),
691+
Some('_') | Some('a'..='z') | Some('A'..='Z') => {
692+
return Some(self.lex_identifier());
693+
}
691694
Some('#') => {
692695
self.lex_comment();
693696
continue;
@@ -1033,7 +1036,7 @@ where
10331036
None => return None,
10341037
_ => {
10351038
let c = self.next_char();
1036-
panic!("Not impl {:?}", c)
1039+
return Some(Err(LexicalError::UnrecognizedToken { tok: c.unwrap() }));
10371040
} // Ignore all the rest..
10381041
}
10391042
}

parser/src/parser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,9 @@ mod tests {
306306

307307
#[test]
308308
fn test_parse_class() {
309-
let source = String::from("class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n");
309+
let source = String::from(
310+
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n",
311+
);
310312
assert_eq!(
311313
parse_statement(&source),
312314
Ok(ast::LocatedStatement {

rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
edition = "2018"

tests/snippets/getframe.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def test_function():
1010
x = 17
1111
assert sys._getframe().f_locals is not locals_dict
1212
assert sys._getframe().f_locals['x'] == 17
13+
assert sys._getframe(1).f_locals['foo'] == 'bar'
1314

1415
test_function()
1516

tests/snippets/ints.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from testutils import assert_raises
2+
13
# int to int comparisons
24

35
assert 1 == 1
@@ -15,6 +17,10 @@
1517
assert 1 >= 1.0
1618
assert 1 <= 1.0
1719

20+
# check for argument handling
21+
22+
assert int("101", base=2) == 5
23+
1824
# magic methods should only be implemented for other ints
1925

2026
assert (1).__eq__(1) == True
@@ -36,6 +42,7 @@
3642
assert (1).real == 1
3743
assert (1).imag == 0
3844

45+
assert_raises(OverflowError, lambda: 1 << 10 ** 100000)
3946

4047
assert (1).__eq__(1.0) == NotImplemented
4148
assert (1).__ne__(1.0) == NotImplemented

tests/snippets/isinstance.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
class Regular:
3+
pass
4+
5+
6+
assert isinstance(Regular(), Regular)
7+
8+
9+
class MCNotInstanceOf(type):
10+
def __instancecheck__(self, instance):
11+
return False
12+
13+
14+
class NotInstanceOf(metaclass=MCNotInstanceOf):
15+
pass
16+
17+
18+
class InheritedNotInstanceOf(NotInstanceOf):
19+
pass
20+
21+
22+
assert not isinstance(Regular(), NotInstanceOf)
23+
assert not isinstance(1, NotInstanceOf)
24+
25+
# weird cpython behaviour if exact match then isinstance return true
26+
assert isinstance(NotInstanceOf(), NotInstanceOf)
27+
assert not NotInstanceOf.__instancecheck__(NotInstanceOf())
28+
assert not isinstance(InheritedNotInstanceOf(), NotInstanceOf)
29+
30+
31+
class MCAlwaysInstanceOf(type):
32+
def __instancecheck__(self, instance):
33+
return True
34+
35+
36+
class AlwaysInstanceOf(metaclass=MCAlwaysInstanceOf):
37+
pass
38+
39+
40+
assert isinstance(AlwaysInstanceOf(), AlwaysInstanceOf)
41+
assert isinstance(Regular(), AlwaysInstanceOf)
42+
assert isinstance(1, AlwaysInstanceOf)
43+
44+
45+
class MCReturnInt(type):
46+
def __instancecheck__(self, instance):
47+
return 3
48+
49+
50+
class ReturnInt(metaclass=MCReturnInt):
51+
pass
52+
53+
54+
assert isinstance("a", ReturnInt) is True

tests/snippets/issubclass.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
2+
class A:
3+
pass
4+
5+
6+
class B(A):
7+
pass
8+
9+
10+
assert issubclass(A, A)
11+
assert issubclass(B, A)
12+
assert not issubclass(A, B)
13+
14+
15+
class MCNotSubClass(type):
16+
def __subclasscheck__(self, subclass):
17+
return False
18+
19+
20+
class NotSubClass(metaclass=MCNotSubClass):
21+
pass
22+
23+
24+
class InheritedNotSubClass(NotSubClass):
25+
pass
26+
27+
28+
assert not issubclass(A, NotSubClass)
29+
assert not issubclass(NotSubClass, NotSubClass)
30+
assert not issubclass(InheritedNotSubClass, NotSubClass)
31+
assert not issubclass(NotSubClass, InheritedNotSubClass)
32+
33+
34+
class MCAlwaysSubClass(type):
35+
def __subclasscheck__(self, subclass):
36+
return True
37+
38+
39+
class AlwaysSubClass(metaclass=MCAlwaysSubClass):
40+
pass
41+
42+
43+
class InheritedAlwaysSubClass(AlwaysSubClass):
44+
pass
45+
46+
47+
assert issubclass(A, AlwaysSubClass)
48+
assert issubclass(AlwaysSubClass, AlwaysSubClass)
49+
assert issubclass(InheritedAlwaysSubClass, AlwaysSubClass)
50+
assert issubclass(AlwaysSubClass, InheritedAlwaysSubClass)
51+
52+
53+
class MCAVirtualSubClass(type):
54+
def __subclasscheck__(self, subclass):
55+
return subclass is A
56+
57+
58+
class AVirtualSubClass(metaclass=MCAVirtualSubClass):
59+
pass
60+
61+
62+
assert issubclass(A, AVirtualSubClass)
63+
assert not isinstance(B, AVirtualSubClass)

tests/snippets/list.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,42 @@ def __eq__(self, x):
117117
assert a == b
118118

119119
assert [foo] == [foo]
120+
121+
for size in [1, 2, 3, 4, 5, 8, 10, 100, 1000]:
122+
lst = list(range(size))
123+
orig = lst[:]
124+
lst.sort()
125+
assert lst == orig
126+
assert sorted(lst) == orig
127+
assert_raises(ZeroDivisionError, lambda: sorted(lst, key=lambda x: 1/x))
128+
lst.reverse()
129+
assert sorted(lst) == orig
130+
assert sorted(lst, reverse=True) == lst
131+
assert sorted(lst, key=lambda x: -x) == lst
132+
assert sorted(lst, key=lambda x: -x, reverse=True) == orig
133+
134+
assert sorted([(1, 2, 3), (0, 3, 6)]) == [(0, 3, 6), (1, 2, 3)]
135+
assert sorted([(1, 2, 3), (0, 3, 6)], key=lambda x: x[0]) == [(0, 3, 6), (1, 2, 3)]
136+
assert sorted([(1, 2, 3), (0, 3, 6)], key=lambda x: x[1]) == [(1, 2, 3), (0, 3, 6)]
137+
assert sorted([(1, 2), (), (5,)], key=len) == [(), (5,), (1, 2)]
138+
139+
lst = [3, 1, 5, 2, 4]
140+
class C:
141+
def __init__(self, x): self.x = x
142+
def __lt__(self, other): return self.x < other.x
143+
lst.sort(key=C)
144+
assert lst == [1, 2, 3, 4, 5]
145+
146+
lst = [3, 1, 5, 2, 4]
147+
class C:
148+
def __init__(self, x): self.x = x
149+
def __gt__(self, other): return self.x > other.x
150+
lst.sort(key=C)
151+
assert lst == [1, 2, 3, 4, 5]
152+
153+
lst = [5, 1, 2, 3, 4]
154+
def f(x):
155+
lst.append(1)
156+
return x
157+
assert_raises(ValueError, lambda: lst.sort(key=f)) # "list modified during sort"
158+
assert lst == [1, 2, 3, 4, 5]

tests/snippets/stdlib_socket.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,37 @@
11
import socket
2+
from testutils import assertRaises
3+
24

35
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4-
listener.bind(("127.0.0.1", 8080))
6+
listener.bind(("127.0.0.1", 0))
57
listener.listen(1)
68

79
connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
8-
connector.connect(("127.0.0.1", 8080))
10+
connector.connect(("127.0.0.1", listener.getsockname()[1]))
911
connection = listener.accept()[0]
1012

1113
message_a = b'aaaa'
1214
message_b = b'bbbbb'
1315

1416
connector.send(message_a)
15-
connector.close()
16-
recv_a = connection.recv(10)
17+
connection.send(message_b)
18+
recv_a = connection.recv(len(message_a))
19+
recv_b = connector.recv(len(message_b))
20+
assert recv_a == message_a
21+
assert recv_b == message_b
1722

1823
connection.close()
24+
connector.close()
1925
listener.close()
2026

27+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
28+
with assertRaises(TypeError):
29+
s.connect(("127.0.0.1", 8888, 8888))
30+
31+
with assertRaises(TypeError):
32+
s.bind(("127.0.0.1", 8888, 8888))
33+
34+
with assertRaises(TypeError):
35+
s.bind((888, 8888))
36+
37+
s.close()

0 commit comments

Comments
 (0)