real-ladybug 0.0.1.dev1__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of real-ladybug might be problematic. Click here for more details.

Files changed (114) hide show
  1. real_ladybug/__init__.py +83 -0
  2. real_ladybug/_lbug.cp312-win_amd64.pyd +0 -0
  3. real_ladybug/_lbug.exp +0 -0
  4. real_ladybug/_lbug.lib +0 -0
  5. real_ladybug/async_connection.py +226 -0
  6. real_ladybug/connection.py +323 -0
  7. real_ladybug/constants.py +7 -0
  8. real_ladybug/database.py +307 -0
  9. real_ladybug/prepared_statement.py +51 -0
  10. real_ladybug/py.typed +0 -0
  11. real_ladybug/query_result.py +511 -0
  12. real_ladybug/torch_geometric_feature_store.py +185 -0
  13. real_ladybug/torch_geometric_graph_store.py +131 -0
  14. real_ladybug/torch_geometric_result_converter.py +282 -0
  15. real_ladybug/types.py +39 -0
  16. real_ladybug-0.0.1.dev1.dist-info/METADATA +88 -0
  17. real_ladybug-0.0.1.dev1.dist-info/RECORD +114 -0
  18. real_ladybug-0.0.1.dev1.dist-info/WHEEL +5 -0
  19. real_ladybug-0.0.1.dev1.dist-info/licenses/LICENSE +21 -0
  20. real_ladybug-0.0.1.dev1.dist-info/top_level.txt +3 -0
  21. real_ladybug-0.0.1.dev1.dist-info/zip-safe +1 -0
  22. real_ladybug-source/scripts/antlr4/hash.py +2 -0
  23. real_ladybug-source/scripts/antlr4/keywordhandler.py +47 -0
  24. real_ladybug-source/scripts/collect-extensions.py +68 -0
  25. real_ladybug-source/scripts/collect-single-file-header.py +126 -0
  26. real_ladybug-source/scripts/export-dbs.py +101 -0
  27. real_ladybug-source/scripts/export-import-test.py +345 -0
  28. real_ladybug-source/scripts/extension/purge-beta.py +34 -0
  29. real_ladybug-source/scripts/generate-cpp-docs/collect_files.py +122 -0
  30. real_ladybug-source/scripts/generate-tinysnb.py +34 -0
  31. real_ladybug-source/scripts/get-clangd-diagnostics.py +233 -0
  32. real_ladybug-source/scripts/migrate-lbug-db.py +308 -0
  33. real_ladybug-source/scripts/multiplatform-test-helper/collect-results.py +71 -0
  34. real_ladybug-source/scripts/multiplatform-test-helper/notify-discord.py +68 -0
  35. real_ladybug-source/scripts/pip-package/package_tar.py +90 -0
  36. real_ladybug-source/scripts/pip-package/setup.py +130 -0
  37. real_ladybug-source/scripts/run-clang-format.py +408 -0
  38. real_ladybug-source/scripts/setup-extension-repo.py +67 -0
  39. real_ladybug-source/scripts/test-simsimd-dispatch.py +45 -0
  40. real_ladybug-source/scripts/update-nightly-build-version.py +81 -0
  41. real_ladybug-source/third_party/brotli/scripts/dictionary/step-01-download-rfc.py +16 -0
  42. real_ladybug-source/third_party/brotli/scripts/dictionary/step-02-rfc-to-bin.py +34 -0
  43. real_ladybug-source/third_party/brotli/scripts/dictionary/step-03-validate-bin.py +35 -0
  44. real_ladybug-source/third_party/brotli/scripts/dictionary/step-04-generate-java-literals.py +85 -0
  45. real_ladybug-source/third_party/pybind11/tools/codespell_ignore_lines_from_errors.py +35 -0
  46. real_ladybug-source/third_party/pybind11/tools/libsize.py +36 -0
  47. real_ladybug-source/third_party/pybind11/tools/make_changelog.py +63 -0
  48. real_ladybug-source/tools/python_api/build/real_ladybug/__init__.py +83 -0
  49. real_ladybug-source/tools/python_api/build/real_ladybug/async_connection.py +226 -0
  50. real_ladybug-source/tools/python_api/build/real_ladybug/connection.py +323 -0
  51. real_ladybug-source/tools/python_api/build/real_ladybug/constants.py +7 -0
  52. real_ladybug-source/tools/python_api/build/real_ladybug/database.py +307 -0
  53. real_ladybug-source/tools/python_api/build/real_ladybug/prepared_statement.py +51 -0
  54. real_ladybug-source/tools/python_api/build/real_ladybug/py.typed +0 -0
  55. real_ladybug-source/tools/python_api/build/real_ladybug/query_result.py +511 -0
  56. real_ladybug-source/tools/python_api/build/real_ladybug/torch_geometric_feature_store.py +185 -0
  57. real_ladybug-source/tools/python_api/build/real_ladybug/torch_geometric_graph_store.py +131 -0
  58. real_ladybug-source/tools/python_api/build/real_ladybug/torch_geometric_result_converter.py +282 -0
  59. real_ladybug-source/tools/python_api/build/real_ladybug/types.py +39 -0
  60. real_ladybug-source/tools/python_api/src_py/__init__.py +83 -0
  61. real_ladybug-source/tools/python_api/src_py/async_connection.py +226 -0
  62. real_ladybug-source/tools/python_api/src_py/connection.py +323 -0
  63. real_ladybug-source/tools/python_api/src_py/constants.py +7 -0
  64. real_ladybug-source/tools/python_api/src_py/database.py +307 -0
  65. real_ladybug-source/tools/python_api/src_py/prepared_statement.py +51 -0
  66. real_ladybug-source/tools/python_api/src_py/py.typed +0 -0
  67. real_ladybug-source/tools/python_api/src_py/query_result.py +511 -0
  68. real_ladybug-source/tools/python_api/src_py/torch_geometric_feature_store.py +185 -0
  69. real_ladybug-source/tools/python_api/src_py/torch_geometric_graph_store.py +131 -0
  70. real_ladybug-source/tools/python_api/src_py/torch_geometric_result_converter.py +282 -0
  71. real_ladybug-source/tools/python_api/src_py/types.py +39 -0
  72. real_ladybug-source/tools/python_api/test/conftest.py +230 -0
  73. real_ladybug-source/tools/python_api/test/disabled_test_extension.py +73 -0
  74. real_ladybug-source/tools/python_api/test/ground_truth.py +430 -0
  75. real_ladybug-source/tools/python_api/test/test_arrow.py +694 -0
  76. real_ladybug-source/tools/python_api/test/test_async_connection.py +159 -0
  77. real_ladybug-source/tools/python_api/test/test_blob_parameter.py +145 -0
  78. real_ladybug-source/tools/python_api/test/test_connection.py +49 -0
  79. real_ladybug-source/tools/python_api/test/test_database.py +234 -0
  80. real_ladybug-source/tools/python_api/test/test_datatype.py +372 -0
  81. real_ladybug-source/tools/python_api/test/test_df.py +564 -0
  82. real_ladybug-source/tools/python_api/test/test_dict.py +112 -0
  83. real_ladybug-source/tools/python_api/test/test_exception.py +54 -0
  84. real_ladybug-source/tools/python_api/test/test_fsm.py +227 -0
  85. real_ladybug-source/tools/python_api/test/test_get_header.py +49 -0
  86. real_ladybug-source/tools/python_api/test/test_helper.py +8 -0
  87. real_ladybug-source/tools/python_api/test/test_issue.py +147 -0
  88. real_ladybug-source/tools/python_api/test/test_iteration.py +96 -0
  89. real_ladybug-source/tools/python_api/test/test_networkx.py +437 -0
  90. real_ladybug-source/tools/python_api/test/test_parameter.py +340 -0
  91. real_ladybug-source/tools/python_api/test/test_prepared_statement.py +117 -0
  92. real_ladybug-source/tools/python_api/test/test_query_result.py +54 -0
  93. real_ladybug-source/tools/python_api/test/test_query_result_close.py +44 -0
  94. real_ladybug-source/tools/python_api/test/test_scan_pandas.py +676 -0
  95. real_ladybug-source/tools/python_api/test/test_scan_pandas_pyarrow.py +714 -0
  96. real_ladybug-source/tools/python_api/test/test_scan_polars.py +165 -0
  97. real_ladybug-source/tools/python_api/test/test_scan_pyarrow.py +167 -0
  98. real_ladybug-source/tools/python_api/test/test_timeout.py +11 -0
  99. real_ladybug-source/tools/python_api/test/test_torch_geometric.py +640 -0
  100. real_ladybug-source/tools/python_api/test/test_torch_geometric_remote_backend.py +111 -0
  101. real_ladybug-source/tools/python_api/test/test_udf.py +207 -0
  102. real_ladybug-source/tools/python_api/test/test_version.py +6 -0
  103. real_ladybug-source/tools/python_api/test/test_wal.py +80 -0
  104. real_ladybug-source/tools/python_api/test/type_aliases.py +10 -0
  105. real_ladybug-source/tools/rust_api/update_version.py +47 -0
  106. real_ladybug-source/tools/shell/test/conftest.py +218 -0
  107. real_ladybug-source/tools/shell/test/test_helper.py +60 -0
  108. real_ladybug-source/tools/shell/test/test_shell_basics.py +325 -0
  109. real_ladybug-source/tools/shell/test/test_shell_commands.py +656 -0
  110. real_ladybug-source/tools/shell/test/test_shell_control_edit.py +438 -0
  111. real_ladybug-source/tools/shell/test/test_shell_control_search.py +468 -0
  112. real_ladybug-source/tools/shell/test/test_shell_esc_edit.py +232 -0
  113. real_ladybug-source/tools/shell/test/test_shell_esc_search.py +162 -0
  114. real_ladybug-source/tools/shell/test/test_shell_flags.py +645 -0
@@ -0,0 +1,60 @@
1
+ import os
2
+ import sys
3
+ from enum import Enum
4
+ from pathlib import Path
5
+
6
+ LBUG_ROOT = Path(__file__).parent.parent.parent.parent
7
+ if sys.platform == "win32":
8
+ # \ in paths is not supported by lbug's parser
9
+ LBUG_ROOT = str(LBUG_ROOT).replace("\\", "/")
10
+
11
+ LBUG_EXEC_PATH = os.path.join(
12
+ LBUG_ROOT,
13
+ "build",
14
+ "release",
15
+ "tools",
16
+ "shell",
17
+ "lbug",
18
+ )
19
+
20
+
21
+ def _get_lbug_version():
22
+ cmake_file = os.path.join(LBUG_ROOT, "CMakeLists.txt")
23
+ with open(cmake_file) as f:
24
+ for line in f:
25
+ if line.startswith("project(Lbug VERSION"):
26
+ return line.split(" ")[2].strip()
27
+ return None
28
+
29
+
30
+ LBUG_VERSION = _get_lbug_version()
31
+
32
+
33
+ class KEY_ACTION(Enum):
34
+ KEY_NULL = "\0" # NULL
35
+ CTRL_A = "a" # Ctrl-a
36
+ CTRL_B = "b" # Ctrl-b
37
+ CTRL_C = "c" # Ctrl-c
38
+ CTRL_D = "d" # Ctrl-d
39
+ CTRL_E = "e" # Ctrl-e
40
+ CTRL_F = "f" # Ctrl-f
41
+ CTRL_G = "g" # Ctrl-g
42
+ CTRL_H = chr(8) # Ctrl-h
43
+ TAB = "\t" # Tab
44
+ CTRL_K = "k" # Ctrl-k
45
+ CTRL_L = "l" # Ctrl-l
46
+ ENTER = "\r" # Enter
47
+ CTRL_N = "n" # Ctrl-n
48
+ CTRL_P = "p" # Ctrl-p
49
+ CTRL_R = "r" # Ctrl-r
50
+ CTRL_S = "s" # Ctrl-s
51
+ CTRL_T = "t" # Ctrl-t
52
+ CTRL_U = "u" # Ctrl-u
53
+ CTRL_W = chr(23) # Ctrl-w
54
+ ESC = "\27" # Escape
55
+ BACKSPACE = chr(127) # Backspace
56
+
57
+
58
+ def deleteIfExists(file) -> None:
59
+ if os.path.exists(file):
60
+ os.remove(file)
@@ -0,0 +1,325 @@
1
+ import os
2
+
3
+ import pexpect
4
+ import pytest
5
+
6
+ from conftest import ShellTest
7
+ from test_helper import deleteIfExists
8
+
9
+
10
+ def test_basic(temp_db) -> None:
11
+ test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" AS a;')
12
+ result = test.run()
13
+ result.check_stdout("\u2502 databases rule \u2502")
14
+
15
+
16
+ def test_range(temp_db) -> None:
17
+ test = ShellTest().add_argument(temp_db).statement("RETURN RANGE(0, 10) AS a;")
18
+ result = test.run()
19
+ result.check_stdout("[0,1,2,3,4,5,6,7,8,9,10]")
20
+
21
+
22
+ @pytest.mark.parametrize(
23
+ ("input", "output"),
24
+ [
25
+ ("RETURN LIST_CREATION(1,2);", "[1,2]"),
26
+ ("RETURN STRUCT_PACK(x:=2,y:=3);", "{x: 2, y: 3}"),
27
+ ("RETURN STRUCT_PACK(x:=2,y:=LIST_CREATION(1,2));", "{x: 2, y: [1,2]}"),
28
+ ],
29
+ )
30
+ def test_nested_types(temp_db, input, output) -> None:
31
+ test = ShellTest().add_argument(temp_db).statement(input)
32
+ result = test.run()
33
+ result.check_stdout(output)
34
+
35
+
36
+ def test_invalid_cast(temp_db) -> None:
37
+ test = (
38
+ ShellTest()
39
+ .add_argument(temp_db)
40
+ .statement("CREATE NODE TABLE a(i STRING, PRIMARY KEY(i));")
41
+ .statement("CREATE (:a {i: '****'});")
42
+ .statement('MATCH (t:a) RETURN CAST(t.i, "INT8");')
43
+ )
44
+ result = test.run()
45
+ result.check_stdout(
46
+ 'Error: Conversion exception: Cast failed. Could not convert "****" to INT8.',
47
+ )
48
+
49
+
50
+ def test_enter_in_between_input(temp_db) -> None:
51
+ test = ShellTest().add_argument(temp_db)
52
+ test.start()
53
+ test.send_statement("CREATE NODE TABLE Test (id INT64 PRIMARY KEY);")
54
+ test.send_statement("\x1b[D" * 5) # left arrow
55
+ test.send_control_statement("j") # ctrl + j
56
+ assert (
57
+ test.shell_process.expect_exact(
58
+ ["\u2502 Table Test has been created. \u2502", pexpect.EOF]
59
+ )
60
+ == 0
61
+ )
62
+
63
+
64
+ def test_multiline(temp_db) -> None:
65
+ test = (
66
+ ShellTest()
67
+ .add_argument(temp_db)
68
+ .statement("RETURN")
69
+ .statement('"databases rule"')
70
+ .statement("AS")
71
+ .statement("a")
72
+ .statement(";")
73
+ )
74
+ result = test.run()
75
+ result.check_stdout("\u2502 databases rule \u2502")
76
+
77
+
78
+ def test_multi_queries_one_line(temp_db) -> None:
79
+ # two successful queries
80
+ test = (
81
+ ShellTest()
82
+ .add_argument(temp_db)
83
+ .statement('RETURN "databases rule" AS a; RETURN "lbug is cool" AS b;')
84
+ )
85
+ result = test.run()
86
+ result.check_stdout("\u2502 databases rule \u2502")
87
+ result.check_stdout("\u2502 lbug is cool \u2502")
88
+
89
+ # one success one failure
90
+ test = (
91
+ ShellTest()
92
+ .add_argument(temp_db)
93
+ .statement('RETURN "databases rule" AS a; RETURN s;')
94
+ )
95
+ result = test.run()
96
+ result.check_stdout("\u2502 databases rule \u2502")
97
+ result.check_stdout("Error: Binder exception: Variable s is not in scope.")
98
+
99
+ # two failing queries
100
+ test = (
101
+ ShellTest()
102
+ .add_argument(temp_db)
103
+ .statement('RETURN "databases rule" S a; RETURN s;')
104
+ )
105
+ result = test.run()
106
+ result.check_stdout(
107
+ [
108
+ "Error: Parser exception: Invalid input < S>: expected rule ku_Statements (line: 1, offset: 24)",
109
+ '"RETURN "databases rule" S a; RETURN s;"',
110
+ " ^",
111
+ ],
112
+ )
113
+
114
+
115
+ def test_row_truncation(temp_db, csv_path) -> None:
116
+ test = (
117
+ ShellTest()
118
+ .add_argument(temp_db)
119
+ .statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN id;')
120
+ )
121
+ result = test.run()
122
+ result.check_stdout("(21 tuples, 20 shown)")
123
+ result.check_stdout(
124
+ [
125
+ "\u2502 \u00b7 \u2502",
126
+ "\u2502 \u00b7 \u2502",
127
+ "\u2502 \u00b7 \u2502",
128
+ ]
129
+ )
130
+
131
+
132
+ def test_column_truncation(temp_db, csv_path) -> None:
133
+ # width when running test is 80
134
+ test = (
135
+ ShellTest()
136
+ .add_argument(temp_db)
137
+ .statement(f'LOAD FROM "{csv_path}" (HEADER=true) RETURN *;')
138
+ )
139
+ result = test.run()
140
+ result.check_stdout("id")
141
+ result.check_stdout("fname")
142
+ result.check_stdout("Gender")
143
+ result.check_stdout("\u2502 ... \u2502")
144
+ result.check_stdout("courseScoresPerTerm")
145
+ result.check_stdout("(13 columns, 4 shown)")
146
+
147
+ # test column name truncation
148
+ long_name = "a" * 100
149
+ test = (
150
+ ShellTest()
151
+ .add_argument(temp_db)
152
+ .statement(f'RETURN "databases rule" AS {long_name};')
153
+ )
154
+ result = test.run()
155
+ result.check_stdout(f"\u2502 {long_name[:73]}... \u2502")
156
+ result.check_stdout("\u2502 databases rule")
157
+
158
+
159
+ def long_messages(temp_db) -> None:
160
+ long_message = "-" * 4096
161
+ test = ShellTest().add_argument(temp_db).statement(f'RETURN "{long_message}" AS a;')
162
+ result = test.run()
163
+ result.check_stdout(long_message)
164
+
165
+
166
+ def test_history_consecutive_repeats(temp_db, history_path) -> None:
167
+ test = (
168
+ ShellTest()
169
+ .add_argument(temp_db)
170
+ .add_argument("-p")
171
+ .add_argument(history_path)
172
+ .statement('RETURN "databases rule" AS a;')
173
+ .statement('RETURN "databases rule" AS a;')
174
+ )
175
+ result = test.run()
176
+ result.check_stdout("\u2502 databases rule \u2502")
177
+
178
+ with open(os.path.join(history_path, "history.txt")) as f:
179
+ assert f.readline() == 'RETURN "databases rule" AS a;\n'
180
+ assert f.readline() == ""
181
+
182
+ deleteIfExists(os.path.join(history_path, "history.txt"))
183
+
184
+
185
+ def test_lbugrc(temp_db) -> None:
186
+ deleteIfExists(".lbugrc")
187
+ # confirm that nothing is read on startup
188
+ test = ShellTest().add_argument(temp_db)
189
+ result = test.run()
190
+ result.check_not_stdout("-- Processing: .lbugrc")
191
+
192
+ # create a .lbugrc file
193
+ with open(".lbugrc", "w") as f:
194
+ f.write("CREATE NODE TABLE a(i STRING, PRIMARY KEY(i));\n")
195
+ f.write(":max_rows 1\n")
196
+
197
+ # confirm that the file is read on startup
198
+ test = ShellTest().add_argument(temp_db).statement("CALL show_tables() RETURN *;")
199
+ result = test.run()
200
+ deleteIfExists(".lbugrc")
201
+ result.check_stdout("-- Processing: .lbugrc")
202
+ result.check_stdout("maxRows set as 1")
203
+ result.check_stdout("a")
204
+
205
+ # create a .lbugrc file with errors
206
+ with open(".lbugrc", "w") as f:
207
+ f.write('RETURN "databases rule" S a; RETURN s;\n')
208
+ f.write(":max_rows\n")
209
+ f.write(":mode table\n")
210
+ f.write("CREATE NODE TABLE b(i STRING, PRIMARY KEY(i));\n")
211
+
212
+ # confirm that the file is read on startup
213
+ test = ShellTest().add_argument(temp_db).statement("CALL show_tables() RETURN *;")
214
+ result = test.run()
215
+ deleteIfExists(".lbugrc")
216
+ result.check_stdout("-- Processing: .lbugrc")
217
+ result.check_stdout(
218
+ [
219
+ "Error: Parser exception: Invalid input < S>: expected rule ku_Statements (line: 1, offset: 24)",
220
+ '"RETURN "databases rule" S a; RETURN s;"',
221
+ " ^",
222
+ ],
223
+ )
224
+ result.check_stdout("Cannot parse '' as number of rows. Expect integer.")
225
+ result.check_stdout("mode set as table")
226
+ result.check_stdout("b")
227
+
228
+
229
+ def test_comments(temp_db) -> None:
230
+ test = (
231
+ ShellTest()
232
+ .add_argument(temp_db)
233
+ .statement(
234
+ 'RETURN // testing\n /* test\ntest\ntest */"databases rule" // testing\n AS a\n; // testing'
235
+ )
236
+ .statement(
237
+ "\x1b[A\r"
238
+ ) # run the last command again to make sure comments are still ignored
239
+ )
240
+ result = test.run()
241
+ result.check_stdout("\u2502 databases rule \u2502")
242
+
243
+
244
+ def test_shell_auto_completion(temp_db) -> None:
245
+ test = ShellTest().add_argument(temp_db)
246
+ test.start()
247
+ test.send_statement(
248
+ "CREATE NODE TABLE coolTable(i STRING, longPropertyName STRING, autoCompleteUINT8 UIN\t"
249
+ )
250
+ test.send_statement("\t")
251
+ test.send_statement("\t")
252
+ test.send_statement("\t")
253
+ test.send_statement(", PRIMARY KEY(i));\n")
254
+ assert (
255
+ test.shell_process.expect_exact(
256
+ ["\u2502 Table coolTable has been created. \u2502", pexpect.EOF]
257
+ )
258
+ == 0
259
+ )
260
+
261
+ test.send_statement("ma\t")
262
+ test.send_statement("\t")
263
+ test.send_statement("\t")
264
+ test.send_statement("\x1b[Z")
265
+ test.send_statement(" (n:\t")
266
+ test.send_statement(") ret\t")
267
+ test.send_statement(" n.\t")
268
+ test.send_statement("\t")
269
+ test.send_finished_statement(";\r")
270
+ assert (
271
+ test.shell_process.expect_exact(
272
+ ["\u2502 n.longPropertyName \u2502", pexpect.EOF]
273
+ )
274
+ == 0
275
+ )
276
+
277
+ test.send_statement("c\t")
278
+ test.send_statement(" show_t\t")
279
+ test.send_statement("() ret\t")
280
+ test.send_finished_statement(" *;\n")
281
+ assert (
282
+ test.shell_process.expect_exact(["\u2502 coolTable \u2502", pexpect.EOF]) == 0
283
+ )
284
+
285
+ test.send_statement("match (a:coolTable)-[]->()-[]->(a:coolTable) ")
286
+ test.send_statement("r")
287
+ test.send_statement("eturn a.lon\t")
288
+ test.send_finished_statement(";\n")
289
+ assert test.shell_process.expect_exact(["(0 tuples)", pexpect.EOF]) == 0
290
+
291
+
292
+ def test_shell_unicode_input(temp_db) -> None:
293
+ test = (
294
+ ShellTest()
295
+ .add_argument(temp_db)
296
+ .statement(
297
+ "CREATE NODE TABLE IF NOT EXISTS `B\\u00fccher` (title STRING, price INT64, PRIMARY KEY (title));\n"
298
+ )
299
+ .statement(
300
+ "CREATE (n:`B\\u00fccher` {title: 'Der Thron der Sieben K\\00f6nigreiche'}) SET n.price = 20;\n"
301
+ )
302
+ .statement("MATCH (n:B\\u00fccher) RETURN label(n);\n")
303
+ .statement(
304
+ 'return "\\uD83D\\uDE01";\n'
305
+ ) # surrogate pair for grinning face emoji
306
+ .statement('return "\\U0001F601";\n') # grinning face emoji
307
+ .statement('return "\\uD83D";\n') # unmatched surrogate pair
308
+ .statement('return "\\uDE01";\n') # unmatched surrogate pair
309
+ .statement('return "\\uD83D\\uDBFF";\n') # bad lower surrogate
310
+ .statement('return "\\u000";\n') # bad unicode codepoint
311
+ .statement('return "\\u0000";\n') # Null character
312
+ .statement('return "\\U00110000";\n') # Invalid codepoint
313
+ )
314
+ result = test.run()
315
+ result.check_stdout("\u2502 B\u00fccher")
316
+ result.check_stdout("\u2502 \U0001f601") # grinning face emoji
317
+ result.check_stdout("\u2502 \U0001f601") # grinning face emoji
318
+ result.check_stdout("Error: Unmatched high surrogate")
319
+ result.check_stdout("Error: Failed to convert codepoint to UTF-8")
320
+ result.check_stdout("Error: Invalid surrogate pair")
321
+ result.check_stdout(
322
+ 'Error: Parser exception: Invalid input <return ">: expected rule oC_RegularQuery (line: 1, offset: 7)'
323
+ )
324
+ result.check_stdout("Error: Null character not allowed")
325
+ result.check_stdout("Error: Invalid Unicode codepoint")