real-ladybug 0.0.1.dev1__cp311-cp311-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.cp311-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,645 @@
1
+ import os
2
+
3
+ import pytest
4
+
5
+ from conftest import ShellTest
6
+ from test_helper import LBUG_VERSION, deleteIfExists
7
+
8
+
9
+ def test_database_path(temp_db) -> None:
10
+ # no database path
11
+ test = ShellTest()
12
+ result = test.run()
13
+ result.check_stdout("Opening the database under in-memory mode.")
14
+
15
+ # valid database path
16
+ test = ShellTest().add_argument(temp_db).statement('RETURN "databases rule" AS a;')
17
+ result = test.run()
18
+ result.check_stdout("databases rule")
19
+
20
+
21
+ @pytest.mark.parametrize(
22
+ "flag",
23
+ ["-h", "--help"],
24
+ )
25
+ def test_help(temp_db, flag) -> None:
26
+ # database path not needed
27
+ test = ShellTest().add_argument(flag)
28
+ result = test.run()
29
+ result.check_stdout("Lbug shell")
30
+ # with database path
31
+ test = ShellTest().add_argument(temp_db).add_argument(flag)
32
+ result = test.run()
33
+ result.check_stdout("Lbug shell")
34
+
35
+
36
+ @pytest.mark.parametrize(
37
+ "flag",
38
+ ["-d", "--defaultbpsize", "--default_bp_size"],
39
+ )
40
+ def test_default_bp_size(temp_db, flag) -> None:
41
+ # empty flag argument
42
+ test = ShellTest().add_argument(temp_db).add_argument(flag)
43
+ result = test.run()
44
+ result.check_stderr(
45
+ f"Flag '{flag.replace('-', '')}' requires an argument but received none",
46
+ )
47
+
48
+ # flag argument is not a number
49
+ test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("lbug")
50
+ result = test.run()
51
+ result.check_stderr("Argument '' received invalid value type 'lbug'")
52
+
53
+ # successful flag
54
+ test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("1000")
55
+ result = test.run()
56
+ result.check_stdout(f"Opening the database at path: {temp_db} in read-write mode.")
57
+
58
+
59
+ @pytest.mark.parametrize(
60
+ "flag",
61
+ ["--maxdbsize", "--max_db_size"],
62
+ )
63
+ def test_max_db_size(temp_db, flag) -> None:
64
+ # empty flag argument
65
+ test = ShellTest().add_argument(temp_db).add_argument(flag)
66
+ result = test.run()
67
+ result.check_stderr(
68
+ f"Flag '{flag.replace('-', '')}' requires an argument but received none",
69
+ )
70
+
71
+ # flag argument is not a number
72
+ test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("lbug")
73
+ result = test.run()
74
+ result.check_stderr("Argument 'max_db_size' received invalid value type 'lbug'")
75
+
76
+ # invalid flag
77
+ test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("1000")
78
+ result = test.run()
79
+ result.check_stderr(
80
+ "Buffer manager exception: The given max db size should be at least 8388608 bytes."
81
+ )
82
+
83
+ # successful flag
84
+ test = ShellTest().add_argument(temp_db).add_argument(flag).add_argument("8388608")
85
+ result = test.run()
86
+ result.check_stdout(f"Opening the database at path: {temp_db} in read-write mode.")
87
+
88
+
89
+ @pytest.mark.parametrize(
90
+ "flag",
91
+ ["--nocompression", "--no_compression"],
92
+ )
93
+ def test_no_compression(temp_db, flag) -> None:
94
+ test = ShellTest().add_argument(temp_db).add_argument(flag)
95
+ result = test.run()
96
+ result.check_stdout(f"Opening the database at path: {temp_db} in read-write mode.")
97
+
98
+
99
+ @pytest.mark.parametrize(
100
+ "flag",
101
+ ["-r", "--readonly", "--read_only"],
102
+ )
103
+ def test_read_only(temp_db, flag) -> None:
104
+ # cannot open an empty database in read only mode so initialize database
105
+ test = ShellTest().add_argument(temp_db)
106
+ result = test.run()
107
+ result.check_stdout(f"Opening the database at path: {temp_db} in read-write mode.")
108
+
109
+ # test read only
110
+ test = (
111
+ ShellTest()
112
+ .add_argument(temp_db)
113
+ .add_argument(flag)
114
+ .statement('RETURN "databases rule" AS a;')
115
+ .statement("CREATE NODE TABLE a(i STRING, PRIMARY KEY(i));")
116
+ .statement('RETURN "lbug is cool" AS b;')
117
+ )
118
+ result = test.run()
119
+ result.check_stdout(f"Opening the database at path: {temp_db} in read-only mode.")
120
+ result.check_stdout("databases rule")
121
+ result.check_stdout(
122
+ "Error: Connection exception: Cannot execute write operations in a read-only database!",
123
+ )
124
+ result.check_stdout("lbug is cool")
125
+
126
+
127
+ def test_history_path(temp_db, history_path) -> None:
128
+ # empty flag argument
129
+ test = ShellTest().add_argument(temp_db).add_argument("-p")
130
+ result = test.run()
131
+ result.check_stderr("Flag 'p' requires an argument but received none")
132
+
133
+ # invalid path
134
+ test = ShellTest().add_argument(temp_db).add_argument("-p").add_argument("///////")
135
+ result = test.run()
136
+ result.check_stderr("Error: failed to open the history file: ///////history.txt")
137
+
138
+ # valid path, file doesn't exist
139
+ test = (
140
+ ShellTest()
141
+ .add_argument(temp_db)
142
+ .add_argument("-p")
143
+ .add_argument(history_path)
144
+ .statement('RETURN "databases rule" AS a;')
145
+ )
146
+ result = test.run()
147
+ result.check_stdout("databases rule")
148
+ with open(os.path.join(history_path, "history.txt")) as f:
149
+ assert f.readline() == 'RETURN "databases rule" AS a;\n'
150
+
151
+ # valid path, file exists
152
+ test = (
153
+ ShellTest()
154
+ .add_argument(temp_db)
155
+ .add_argument("-p")
156
+ .add_argument(history_path)
157
+ .statement('RETURN "lbug is cool" AS b;')
158
+ )
159
+ result = test.run()
160
+ with open(os.path.join(history_path, "history.txt")) as f:
161
+ assert f.readline() == 'RETURN "databases rule" AS a;\n'
162
+ assert f.readline() == 'RETURN "lbug is cool" AS b;\n'
163
+
164
+ deleteIfExists(os.path.join(history_path, "history.txt"))
165
+
166
+
167
+ @pytest.mark.parametrize(
168
+ "flag",
169
+ [
170
+ "-v",
171
+ "--version",
172
+ ],
173
+ )
174
+ def test_version(temp_db, flag) -> None:
175
+ # database path not needed
176
+ test = ShellTest().add_argument(flag)
177
+ result = test.run()
178
+ result.check_stdout(LBUG_VERSION)
179
+ # with database path
180
+ test = ShellTest().add_argument(temp_db).add_argument(flag)
181
+ result = test.run()
182
+ result.check_stdout(LBUG_VERSION)
183
+
184
+
185
+ @pytest.mark.parametrize(
186
+ "flag",
187
+ [
188
+ "-m",
189
+ "--mode",
190
+ ],
191
+ )
192
+ def test_mode(temp_db, flag) -> None:
193
+ # test default mode
194
+ test = (
195
+ ShellTest()
196
+ .add_argument(temp_db)
197
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
198
+ )
199
+ result = test.run()
200
+ result.check_stdout("\u2502 a \u2502 b \u2502")
201
+ result.check_stdout("\u2502 Databases Rule \u2502 lbug is cool \u2502")
202
+
203
+ # test column mode
204
+ test = (
205
+ ShellTest()
206
+ .add_argument(temp_db)
207
+ .add_argument(flag)
208
+ .add_argument("column")
209
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
210
+ )
211
+ result = test.run()
212
+ result.check_stdout("a b")
213
+ result.check_stdout("Databases Rule lbug is cool")
214
+
215
+ # test csv mode
216
+ test = (
217
+ ShellTest()
218
+ .add_argument(temp_db)
219
+ .add_argument(flag)
220
+ .add_argument("csv")
221
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
222
+ )
223
+ result = test.run()
224
+ result.check_stdout("a,b")
225
+ result.check_stdout("Databases Rule,lbug is cool")
226
+
227
+ # test csv escaping
228
+ test = (
229
+ ShellTest()
230
+ .add_argument(temp_db)
231
+ .add_argument(flag)
232
+ .add_argument("csv")
233
+ .statement(
234
+ 'RETURN "This is a \\"test\\", with commas, \\"quotes\\", and\nnewlines.";'
235
+ )
236
+ )
237
+ result = test.run()
238
+ result.check_stdout('"This is a ""test"", with commas, ""quotes"", and\nnewlines."')
239
+
240
+ # test box mode
241
+ test = (
242
+ ShellTest()
243
+ .add_argument(temp_db)
244
+ .add_argument(flag)
245
+ .add_argument("box")
246
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
247
+ )
248
+ result = test.run()
249
+ result.check_stdout("\u2502 a \u2502 b \u2502")
250
+ result.check_stdout("\u2502 Databases Rule \u2502 lbug is cool \u2502")
251
+
252
+ # test html mode
253
+ test = (
254
+ ShellTest()
255
+ .add_argument(temp_db)
256
+ .add_argument(flag)
257
+ .add_argument("html")
258
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
259
+ )
260
+ result = test.run()
261
+ result.check_stdout("<table>")
262
+ result.check_stdout("<tr>")
263
+ result.check_stdout("<th>a</th><th>b</th>")
264
+ result.check_stdout("</tr>")
265
+ result.check_stdout("<tr>")
266
+ result.check_stdout("<td>Databases Rule</td><td>lbug is cool</td>")
267
+ result.check_stdout("</tr>")
268
+ result.check_stdout("</table>")
269
+
270
+ # test html escaping
271
+ test = (
272
+ ShellTest()
273
+ .add_argument(temp_db)
274
+ .add_argument(flag)
275
+ .add_argument("html")
276
+ .statement(
277
+ 'RETURN "This is a <test> & \\"example\\" with \'special\' characters." AS a;'
278
+ )
279
+ )
280
+ result = test.run()
281
+ result.check_stdout("<table>")
282
+ result.check_stdout("<tr>")
283
+ result.check_stdout("<th>a</th>")
284
+ result.check_stdout("</tr>")
285
+ result.check_stdout("<tr>")
286
+ result.check_stdout(
287
+ "<td>This is a &lt;test&gt; &amp; &quot;example&quot; with &apos;special&apos; characters.</td>"
288
+ )
289
+ result.check_stdout("</tr>")
290
+ result.check_stdout("</table>")
291
+
292
+ # test json mode
293
+ test = (
294
+ ShellTest()
295
+ .add_argument(temp_db)
296
+ .add_argument(flag)
297
+ .add_argument("json")
298
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
299
+ )
300
+ result = test.run()
301
+ result.check_stdout('[\n{"a":"Databases Rule","b":"lbug is cool"}\n]')
302
+
303
+ # test json escaping
304
+ test = (
305
+ ShellTest()
306
+ .add_argument(temp_db)
307
+ .add_argument(flag)
308
+ .add_argument("json")
309
+ .statement(
310
+ 'RETURN "This is a \\"test\\" with backslashes \\\\, newlines\n, and tabs \t." AS a;'
311
+ )
312
+ )
313
+ result = test.run()
314
+ result.check_stdout(
315
+ '[\n{"a":"This is a \\"test\\" with backslashes \\\\, newlines\\n, and tabs \\t."}\n]'
316
+ )
317
+
318
+ # test jsonlines mode
319
+ test = (
320
+ ShellTest()
321
+ .add_argument(temp_db)
322
+ .add_argument(flag)
323
+ .add_argument("jsonlines")
324
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
325
+ )
326
+ result = test.run()
327
+ result.check_stdout('{"a":"Databases Rule","b":"lbug is cool"}')
328
+
329
+ # test jsonlines escaping
330
+ test = (
331
+ ShellTest()
332
+ .add_argument(temp_db)
333
+ .add_argument(flag)
334
+ .add_argument("jsonlines")
335
+ .statement(
336
+ 'RETURN "This is a \\"test\\" with backslashes \\\\, newlines\n, and tabs \t." AS a;'
337
+ )
338
+ )
339
+ result = test.run()
340
+ result.check_stdout(
341
+ '{"a":"This is a \\"test\\" with backslashes \\\\, newlines\\n, and tabs \\t."}'
342
+ )
343
+
344
+ # test latex mode
345
+ test = (
346
+ ShellTest()
347
+ .add_argument(temp_db)
348
+ .add_argument(flag)
349
+ .add_argument("latex")
350
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
351
+ )
352
+ result = test.run()
353
+ result.check_stdout("\\begin{tabular}{ll}")
354
+ result.check_stdout("\\hline")
355
+ result.check_stdout("a&b\\\\")
356
+ result.check_stdout("\\hline")
357
+ result.check_stdout("Databases Rule&lbug is cool\\\\")
358
+ result.check_stdout("\\hline")
359
+ result.check_stdout("\\end{tabular}")
360
+
361
+ # test latex escaping
362
+ test = (
363
+ ShellTest()
364
+ .add_argument(temp_db)
365
+ .add_argument(flag)
366
+ .add_argument("latex")
367
+ .statement(
368
+ 'RETURN "This is a test with special characters: %, $, &, #, _, {, }, ~, ^, \\\\, <, and >." AS a;'
369
+ )
370
+ )
371
+ result = test.run()
372
+ result.check_stdout("\\begin{tabular}{l}")
373
+ result.check_stdout("\\hline")
374
+ result.check_stdout("a\\\\")
375
+ result.check_stdout("\\hline")
376
+ result.check_stdout(
377
+ "This is a test with special characters: \\%, \\$, \\&, \\#, \\_, \\{, \\}, \\textasciitilde{}, \\textasciicircum{}, \\textbackslash{}, \\textless{}, and \\textgreater{}.\\\\"
378
+ )
379
+ result.check_stdout("\\hline")
380
+ result.check_stdout("\\end{tabular}")
381
+
382
+ # test line mode
383
+ test = (
384
+ ShellTest()
385
+ .add_argument(temp_db)
386
+ .add_argument(flag)
387
+ .add_argument("line")
388
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
389
+ )
390
+ result = test.run()
391
+ result.check_stdout("a = Databases Rule")
392
+ result.check_stdout("b = lbug is cool")
393
+
394
+ # test list mode
395
+ test = (
396
+ ShellTest()
397
+ .add_argument(temp_db)
398
+ .add_argument(flag)
399
+ .add_argument("list")
400
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
401
+ )
402
+ result = test.run()
403
+ result.check_stdout("a|b")
404
+ result.check_stdout("Databases Rule|lbug is cool")
405
+
406
+ # test list escaping
407
+ test = (
408
+ ShellTest()
409
+ .add_argument(temp_db)
410
+ .add_argument(flag)
411
+ .add_argument("list")
412
+ .statement(
413
+ 'RETURN "This is a \\"test\\", with vertical bars |, \\"quotes\\", and\nnewlines.";'
414
+ )
415
+ )
416
+ result = test.run()
417
+ result.check_stdout(
418
+ '"This is a ""test"", with vertical bars |, ""quotes"", and\nnewlines."'
419
+ )
420
+
421
+ # test markdown mode
422
+ test = (
423
+ ShellTest()
424
+ .add_argument(temp_db)
425
+ .add_argument(flag)
426
+ .add_argument("markdown")
427
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
428
+ )
429
+ result = test.run()
430
+ result.check_stdout("| a | b |")
431
+ result.check_stdout("| Databases Rule | lbug is cool |")
432
+
433
+ # test table mode
434
+ test = (
435
+ ShellTest()
436
+ .add_argument(temp_db)
437
+ .add_argument(flag)
438
+ .add_argument("table")
439
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
440
+ )
441
+ result = test.run()
442
+ result.check_stdout("| a | b |")
443
+ result.check_stdout("| Databases Rule | lbug is cool |")
444
+
445
+ # test tsv mode
446
+ test = (
447
+ ShellTest()
448
+ .add_argument(temp_db)
449
+ .add_argument(flag)
450
+ .add_argument("tsv")
451
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
452
+ )
453
+ result = test.run()
454
+ result.check_stdout("a\tb")
455
+ result.check_stdout("Databases Rule\tlbug is cool")
456
+
457
+ # test tsv escaping
458
+ test = (
459
+ ShellTest()
460
+ .add_argument(temp_db)
461
+ .add_argument(flag)
462
+ .add_argument("tsv")
463
+ .statement(
464
+ 'RETURN "This is a \\"test\\", with tabs \t, \\"quotes\\", and\nnewlines.";'
465
+ )
466
+ )
467
+ result = test.run()
468
+ result.check_stdout(
469
+ '"This is a ""test"", with tabs \t, ""quotes"", and\nnewlines."'
470
+ )
471
+
472
+ # test trash mode
473
+ test = (
474
+ ShellTest()
475
+ .add_argument(temp_db)
476
+ .add_argument(flag)
477
+ .add_argument("trash")
478
+ .statement("RETURN RANGE(0, 10) AS a;")
479
+ )
480
+ result = test.run()
481
+ result.check_not_stdout("[0,1,2,3,4,5,6,7,8,9,10]")
482
+
483
+ # test mode info
484
+ test = (
485
+ ShellTest()
486
+ .add_argument(temp_db)
487
+ .add_argument(flag)
488
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
489
+ )
490
+ result = test.run()
491
+ result.check_stderr(
492
+ f"Flag '{flag.replace('-', '')}' requires an argument but received none"
493
+ )
494
+
495
+ # test invalid mode
496
+ test = (
497
+ ShellTest()
498
+ .add_argument(temp_db)
499
+ .add_argument(flag)
500
+ .add_argument("invalid")
501
+ .statement('RETURN "Databases Rule" AS a, "lbug is cool" AS b;')
502
+ )
503
+ result = test.run()
504
+ result.check_stderr("Error: cannot parse output mode: invalid")
505
+
506
+
507
+ @pytest.mark.parametrize(
508
+ "flag",
509
+ [
510
+ "-s",
511
+ "--nostats",
512
+ "--no_stats",
513
+ ],
514
+ )
515
+ def test_no_stats(temp_db, flag) -> None:
516
+ # test stats off
517
+ test = (
518
+ ShellTest()
519
+ .add_argument(temp_db)
520
+ .add_argument(flag)
521
+ .statement('RETURN "Databases Rule" AS a;')
522
+ )
523
+ result = test.run()
524
+ result.check_not_stdout("(1 tuple)")
525
+ result.check_not_stdout("(1 column)")
526
+ result.check_not_stdout("Time: ")
527
+
528
+ # test stats on
529
+ test = ShellTest().add_argument(temp_db).statement('RETURN "Databases Rule" AS a;')
530
+ result = test.run()
531
+ result.check_stdout("(1 tuple)")
532
+ result.check_stdout("(1 column)")
533
+ result.check_stdout("Time: ")
534
+
535
+
536
+ @pytest.mark.parametrize(
537
+ "flag",
538
+ ["-b", "--no_progress_bar", "--noprogressbar"],
539
+ )
540
+ def test_no_progress_bar(temp_db, flag) -> None:
541
+ # progress bar on by default
542
+ test = (
543
+ ShellTest()
544
+ .add_argument(temp_db)
545
+ .statement("CALL current_setting('progress_bar') RETURN *;")
546
+ )
547
+ result = test.run()
548
+ result.check_stdout("True")
549
+
550
+ # progress bar off
551
+ test = (
552
+ ShellTest()
553
+ .add_argument(temp_db)
554
+ .add_argument(flag)
555
+ .statement("CALL current_setting('progress_bar') RETURN *;")
556
+ )
557
+ result = test.run()
558
+ print(result.stdout)
559
+ print(result.stderr)
560
+ result.check_stdout("False")
561
+
562
+
563
+ @pytest.mark.parametrize(
564
+ "flag",
565
+ ["-w", "--ignore_wal_replay_errors"],
566
+ )
567
+ def test_ignore_wal_replay_errors(temp_db, flag) -> None:
568
+ # Create an initial DB
569
+ test = ShellTest().add_argument(temp_db).statement("return 1")
570
+ result = test.run()
571
+
572
+ # create garbage WAL file
573
+ with open(temp_db + ".wal", "w") as wal_file:
574
+ wal_file.write("abcdefghijklmnopqrstuvwxyz")
575
+
576
+ # Test with ignore_wal_replay_errors off
577
+ test = ShellTest().add_argument(temp_db)
578
+ result = test.run()
579
+ result.check_stderr("Checksum verification failed")
580
+
581
+ # Test with ignore_wal_replay_errors on
582
+ with open(temp_db + ".wal", "w") as wal_file:
583
+ wal_file.write("abcdefghijklmnopqrstuvwxyz")
584
+ test = ShellTest().add_argument(temp_db).add_argument(flag).statement("RETURN 1")
585
+ result = test.run()
586
+ result.check_stdout("1")
587
+
588
+
589
+ @pytest.mark.parametrize(
590
+ "flag",
591
+ [
592
+ "-i",
593
+ "--init",
594
+ ],
595
+ )
596
+ def test_init(temp_db, init_path, flag) -> None:
597
+ # without init
598
+ test = ShellTest().add_argument(temp_db).statement("CALL show_tables() RETURN *;")
599
+ result = test.run()
600
+ result.check_not_stdout("person")
601
+ result.check_not_stdout("organisation")
602
+ result.check_not_stdout("movies")
603
+ result.check_not_stdout("knows")
604
+ result.check_not_stdout("studyAt")
605
+ result.check_not_stdout("workAt")
606
+ result.check_not_stdout("meets")
607
+ result.check_not_stdout("marries")
608
+
609
+ # with init
610
+ test = (
611
+ ShellTest()
612
+ .add_argument(temp_db)
613
+ .add_argument(flag)
614
+ .add_argument(init_path)
615
+ .statement("CALL show_tables() RETURN *;")
616
+ )
617
+ result = test.run()
618
+ result.check_stdout("person")
619
+ result.check_stdout("organisation")
620
+ result.check_stdout("movies")
621
+ result.check_stdout("knows")
622
+ result.check_stdout("studyAt")
623
+ result.check_stdout("workAt")
624
+ result.check_stdout("meets")
625
+ result.check_stdout("marries")
626
+
627
+
628
+ def test_bad_flag(temp_db) -> None:
629
+ # without database path
630
+ test = ShellTest().add_argument("-a")
631
+ result = test.run()
632
+ result.check_stderr("Flag could not be matched: 'a'")
633
+
634
+ test = ShellTest().add_argument("--badflag")
635
+ result = test.run()
636
+ result.check_stderr("Flag could not be matched: badflag")
637
+
638
+ # with database path
639
+ test = ShellTest().add_argument(temp_db).add_argument("-a")
640
+ result = test.run()
641
+ result.check_stderr("Flag could not be matched: 'a'")
642
+
643
+ test = ShellTest().add_argument(temp_db).add_argument("--badflag")
644
+ result = test.run()
645
+ result.check_stderr("Flag could not be matched: badflag")