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.
- real_ladybug/__init__.py +83 -0
- real_ladybug/_lbug.cp312-win_amd64.pyd +0 -0
- real_ladybug/_lbug.exp +0 -0
- real_ladybug/_lbug.lib +0 -0
- real_ladybug/async_connection.py +226 -0
- real_ladybug/connection.py +323 -0
- real_ladybug/constants.py +7 -0
- real_ladybug/database.py +307 -0
- real_ladybug/prepared_statement.py +51 -0
- real_ladybug/py.typed +0 -0
- real_ladybug/query_result.py +511 -0
- real_ladybug/torch_geometric_feature_store.py +185 -0
- real_ladybug/torch_geometric_graph_store.py +131 -0
- real_ladybug/torch_geometric_result_converter.py +282 -0
- real_ladybug/types.py +39 -0
- real_ladybug-0.0.1.dev1.dist-info/METADATA +88 -0
- real_ladybug-0.0.1.dev1.dist-info/RECORD +114 -0
- real_ladybug-0.0.1.dev1.dist-info/WHEEL +5 -0
- real_ladybug-0.0.1.dev1.dist-info/licenses/LICENSE +21 -0
- real_ladybug-0.0.1.dev1.dist-info/top_level.txt +3 -0
- real_ladybug-0.0.1.dev1.dist-info/zip-safe +1 -0
- real_ladybug-source/scripts/antlr4/hash.py +2 -0
- real_ladybug-source/scripts/antlr4/keywordhandler.py +47 -0
- real_ladybug-source/scripts/collect-extensions.py +68 -0
- real_ladybug-source/scripts/collect-single-file-header.py +126 -0
- real_ladybug-source/scripts/export-dbs.py +101 -0
- real_ladybug-source/scripts/export-import-test.py +345 -0
- real_ladybug-source/scripts/extension/purge-beta.py +34 -0
- real_ladybug-source/scripts/generate-cpp-docs/collect_files.py +122 -0
- real_ladybug-source/scripts/generate-tinysnb.py +34 -0
- real_ladybug-source/scripts/get-clangd-diagnostics.py +233 -0
- real_ladybug-source/scripts/migrate-lbug-db.py +308 -0
- real_ladybug-source/scripts/multiplatform-test-helper/collect-results.py +71 -0
- real_ladybug-source/scripts/multiplatform-test-helper/notify-discord.py +68 -0
- real_ladybug-source/scripts/pip-package/package_tar.py +90 -0
- real_ladybug-source/scripts/pip-package/setup.py +130 -0
- real_ladybug-source/scripts/run-clang-format.py +408 -0
- real_ladybug-source/scripts/setup-extension-repo.py +67 -0
- real_ladybug-source/scripts/test-simsimd-dispatch.py +45 -0
- real_ladybug-source/scripts/update-nightly-build-version.py +81 -0
- real_ladybug-source/third_party/brotli/scripts/dictionary/step-01-download-rfc.py +16 -0
- real_ladybug-source/third_party/brotli/scripts/dictionary/step-02-rfc-to-bin.py +34 -0
- real_ladybug-source/third_party/brotli/scripts/dictionary/step-03-validate-bin.py +35 -0
- real_ladybug-source/third_party/brotli/scripts/dictionary/step-04-generate-java-literals.py +85 -0
- real_ladybug-source/third_party/pybind11/tools/codespell_ignore_lines_from_errors.py +35 -0
- real_ladybug-source/third_party/pybind11/tools/libsize.py +36 -0
- real_ladybug-source/third_party/pybind11/tools/make_changelog.py +63 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/__init__.py +83 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/async_connection.py +226 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/connection.py +323 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/constants.py +7 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/database.py +307 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/prepared_statement.py +51 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/py.typed +0 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/query_result.py +511 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/torch_geometric_feature_store.py +185 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/torch_geometric_graph_store.py +131 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/torch_geometric_result_converter.py +282 -0
- real_ladybug-source/tools/python_api/build/real_ladybug/types.py +39 -0
- real_ladybug-source/tools/python_api/src_py/__init__.py +83 -0
- real_ladybug-source/tools/python_api/src_py/async_connection.py +226 -0
- real_ladybug-source/tools/python_api/src_py/connection.py +323 -0
- real_ladybug-source/tools/python_api/src_py/constants.py +7 -0
- real_ladybug-source/tools/python_api/src_py/database.py +307 -0
- real_ladybug-source/tools/python_api/src_py/prepared_statement.py +51 -0
- real_ladybug-source/tools/python_api/src_py/py.typed +0 -0
- real_ladybug-source/tools/python_api/src_py/query_result.py +511 -0
- real_ladybug-source/tools/python_api/src_py/torch_geometric_feature_store.py +185 -0
- real_ladybug-source/tools/python_api/src_py/torch_geometric_graph_store.py +131 -0
- real_ladybug-source/tools/python_api/src_py/torch_geometric_result_converter.py +282 -0
- real_ladybug-source/tools/python_api/src_py/types.py +39 -0
- real_ladybug-source/tools/python_api/test/conftest.py +230 -0
- real_ladybug-source/tools/python_api/test/disabled_test_extension.py +73 -0
- real_ladybug-source/tools/python_api/test/ground_truth.py +430 -0
- real_ladybug-source/tools/python_api/test/test_arrow.py +694 -0
- real_ladybug-source/tools/python_api/test/test_async_connection.py +159 -0
- real_ladybug-source/tools/python_api/test/test_blob_parameter.py +145 -0
- real_ladybug-source/tools/python_api/test/test_connection.py +49 -0
- real_ladybug-source/tools/python_api/test/test_database.py +234 -0
- real_ladybug-source/tools/python_api/test/test_datatype.py +372 -0
- real_ladybug-source/tools/python_api/test/test_df.py +564 -0
- real_ladybug-source/tools/python_api/test/test_dict.py +112 -0
- real_ladybug-source/tools/python_api/test/test_exception.py +54 -0
- real_ladybug-source/tools/python_api/test/test_fsm.py +227 -0
- real_ladybug-source/tools/python_api/test/test_get_header.py +49 -0
- real_ladybug-source/tools/python_api/test/test_helper.py +8 -0
- real_ladybug-source/tools/python_api/test/test_issue.py +147 -0
- real_ladybug-source/tools/python_api/test/test_iteration.py +96 -0
- real_ladybug-source/tools/python_api/test/test_networkx.py +437 -0
- real_ladybug-source/tools/python_api/test/test_parameter.py +340 -0
- real_ladybug-source/tools/python_api/test/test_prepared_statement.py +117 -0
- real_ladybug-source/tools/python_api/test/test_query_result.py +54 -0
- real_ladybug-source/tools/python_api/test/test_query_result_close.py +44 -0
- real_ladybug-source/tools/python_api/test/test_scan_pandas.py +676 -0
- real_ladybug-source/tools/python_api/test/test_scan_pandas_pyarrow.py +714 -0
- real_ladybug-source/tools/python_api/test/test_scan_polars.py +165 -0
- real_ladybug-source/tools/python_api/test/test_scan_pyarrow.py +167 -0
- real_ladybug-source/tools/python_api/test/test_timeout.py +11 -0
- real_ladybug-source/tools/python_api/test/test_torch_geometric.py +640 -0
- real_ladybug-source/tools/python_api/test/test_torch_geometric_remote_backend.py +111 -0
- real_ladybug-source/tools/python_api/test/test_udf.py +207 -0
- real_ladybug-source/tools/python_api/test/test_version.py +6 -0
- real_ladybug-source/tools/python_api/test/test_wal.py +80 -0
- real_ladybug-source/tools/python_api/test/type_aliases.py +10 -0
- real_ladybug-source/tools/rust_api/update_version.py +47 -0
- real_ladybug-source/tools/shell/test/conftest.py +218 -0
- real_ladybug-source/tools/shell/test/test_helper.py +60 -0
- real_ladybug-source/tools/shell/test/test_shell_basics.py +325 -0
- real_ladybug-source/tools/shell/test/test_shell_commands.py +656 -0
- real_ladybug-source/tools/shell/test/test_shell_control_edit.py +438 -0
- real_ladybug-source/tools/shell/test/test_shell_control_search.py +468 -0
- real_ladybug-source/tools/shell/test/test_shell_esc_edit.py +232 -0
- real_ladybug-source/tools/shell/test/test_shell_esc_search.py +162 -0
- 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")
|