turbo-editors/turbo-pythonpublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-python.git
git clone ssh://git@rickub.com/turbo-editors/turbo-python.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

reference_test.go · 90 lines · 3.5 KBGo Blame HistoryRaw
📦 Turbo Python 6fc62ea k33g 9h ago1package pythonlang
2
3import (
4 "strings"
5 "testing"
6
7 "rickub.com/turbo-editors/turbo-core/syntax"
8)
9
10// TestTheLanguagesReferenceIsTrue holds docs/*/reference/languages.md to the
11// scanner. Every row of its Python table that no other test here covers is
12// checked, so a reference claim and the code cannot drift apart quietly.
13//
14// The last three cases document *limitations* rather than features — an
15// all-capital class name read as a constant, `type` read as the builtin rather
16// than as a soft keyword, an f-string's braces left inside the string. The
17// reference says each of those in so many words, and these rows are what stops
18// somebody "fixing" one without also fixing the sentence.
19func TestTheLanguagesReferenceIsTrue(t *testing.T) {
20 tests := []struct {
21 src string
22 word string
23 want syntax.Class
24 }{
25 {"assert x is not None", "assert", syntax.ClassKeyword},
26 {"nonlocal counter", "nonlocal", syntax.ClassKeyword},
27 {"async def f() -> None:\n pass\n", "async", syntax.ClassKeyword},
28 {"x = NotImplemented", "NotImplemented", syntax.ClassConstant},
29 {"x = Ellipsis", "Ellipsis", syntax.ClassConstant},
30 {"if __debug__:\n pass\n", "__debug__", syntax.ClassConstant},
31 {"x: frozenset = frozenset()", "frozenset", syntax.ClassType},
32 {"x: memoryview = m", "memoryview", syntax.ClassType},
33 {"x = isinstance(v, int)", "isinstance", syntax.ClassBuiltin},
34 {"x = sorted(v)", "sorted", syntax.ClassBuiltin},
35 {"def f(cls) -> None:\n pass\n", "cls", syntax.ClassBuiltin},
36 {"x = obj.__name__", "__name__", syntax.ClassBuiltin},
37 {`x = rb"raw bytes"`, `rb"raw bytes"`, syntax.ClassString},
38 {`x = BR"raw bytes"`, `BR"raw bytes"`, syntax.ClassString},
39 {`x = u"text"`, `u"text"`, syntax.ClassString},
40 {"x = 0o17", "0o17", syntax.ClassNumber},
41 {"x = 0b1010", "0b1010", syntax.ClassNumber},
42 {"x = 3j", "3j", syntax.ClassNumber},
43 {"x = 1E+7", "1E+7", syntax.ClassNumber},
44 {"#!/usr/bin/env python3", "#!/usr/bin/env python3", syntax.ClassComment},
45 {"@property\ndef x(self):\n pass\n", "@property", syntax.ClassAttribute},
46 {"if (n := f()) > 1:\n pass\n", ":=", syntax.ClassOperator},
47 {"d = {1: 2}", ":", syntax.ClassPunctuation},
48 {"x = a @ b", "@", syntax.ClassOperator},
49 {"x = 1 + \\", "\\", syntax.ClassPunctuation},
50 {"x = [1, 2]", "[", syntax.ClassPunctuation},
51
52 // The documented limitations.
53 {"HTTP = 1", "HTTP", syntax.ClassConstant},
54 {"type Alias = int", "type", syntax.ClassType},
55 {"match value: # dispatch\n", "match", syntax.ClassIdentifier},
56 }
57
58 for _, test := range tests {
59 t.Run(test.word, func(t *testing.T) {
60 index := strings.Index(test.src, test.word)
61 if index < 0 {
62 t.Fatalf("%q not in %q", test.word, test.src)
63 }
64 got, ok := classAt(Highlight(test.src), 0, index)
65 if !ok || got != test.want {
66 t.Errorf("%q in %q is %v (covered %v), want %v", test.word, test.src, got, ok, test.want)
67 }
68 })
69 }
70}
71
72// The reference's Python table says the class `char` is produced by nothing
73// here, because Python has no character type. That is a claim about every span
74// the scanner can ever emit, so it is checked over a file that uses every
75// construct the table names.
76func TestTheScannerNeverProducesACharacterClass(t *testing.T) {
77 const src = "#!/usr/bin/env python3\n" +
78 "x = 'single'\n" +
79 "y = \"double\"\n" +
80 "z = b'bytes'\n" +
81 "w = '''triple'''\n"
82
83 for line, spans := range Highlight(src) {
84 for _, span := range spans {
85 if span.Class == syntax.ClassChar {
86 t.Errorf("line %d holds a char span at %d; Python has no character literal", line, span.Start)
87 }
88 }
89 }
90}