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,340 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime
4
+ from typing import TYPE_CHECKING
5
+
6
+ import pytest
7
+ from type_aliases import ConnDB
8
+
9
+ # required by python-lint
10
+ if TYPE_CHECKING:
11
+ from pathlib import Path
12
+ import real_ladybug as lb
13
+
14
+
15
+ def test_struct_param_access(conn_db_readwrite: ConnDB) -> None:
16
+ conn, _ = conn_db_readwrite
17
+ batch = [
18
+ {
19
+ "id": "1",
20
+ "name": "Christopher",
21
+ "age": "61",
22
+ "net_worth": "21561030.8",
23
+ "email": "wilcox@hotmail.com",
24
+ "address": "588 Campbell Well Suite 335, Lawrencemouth, VI 07241",
25
+ "phone": "358-202-1821x630",
26
+ "comments": "Stage modern card send point future serve. Hot month might pass dinner chance.\nPerformance become own spring from analysis commercial. Draw effort structure many drug first.",
27
+ },
28
+ {
29
+ "id": "2",
30
+ "name": "Amanda",
31
+ "age": "42",
32
+ "net_worth": "31344480.2",
33
+ "email": "cook@hotmail.com",
34
+ "address": "6293 Bright Centers, Chenton, MO 36829",
35
+ "phone": "001-972-387-3913x966",
36
+ "comments": "None agent some if skill. Often onto dog wish. Listen live hair garden contain worry time. Economic or institution statement energy take sit.",
37
+ },
38
+ ]
39
+ conn.execute(
40
+ """
41
+ UNWIND $batch AS p
42
+ RETURN p.name,
43
+ p.age,
44
+ p.net_worth,
45
+ p.email,
46
+ p.address,
47
+ p.phone,
48
+ p.comments
49
+ """,
50
+ parameters={"batch": batch},
51
+ )
52
+
53
+
54
+ def test_array_binding(conn_db_readwrite: ConnDB) -> None:
55
+ conn, _ = conn_db_readwrite
56
+ conn.execute("CREATE NODE TABLE node(id STRING, embedding DOUBLE[3], PRIMARY KEY(id))")
57
+ conn.execute("CREATE (d:node {id: 'test', embedding: $emb})", {"emb": [3, 5, 2]})
58
+ result = conn.execute(
59
+ """
60
+ MATCH (d:node)
61
+ RETURN d.id, array_cosine_similarity(d.embedding, $emb)
62
+ """,
63
+ {"emb": [4.3, 5.2, 6.7]},
64
+ )
65
+ assert result.get_next() == ["test", pytest.approx(0.8922316795174099)]
66
+ # TODO(maxwell): fixme. The following case should be executed successfully.
67
+ # with pytest.raises(RuntimeError) as err:
68
+ # conn.execute(
69
+ # """
70
+ # MATCH (d:node)
71
+ # RETURN d.id, array_cosine_similarity($emb1, $emb)
72
+ # """, {"emb": [4.3, 5.2, 6.7], "emb1": [2.2, 3.3, 5.5]}
73
+ # )
74
+ # assert str(err.value) == "Binder exception: Left and right type are both ANY, which is not currently supported."
75
+
76
+
77
+ def test_bool_param(conn_db_readonly: ConnDB) -> None:
78
+ conn, _ = conn_db_readonly
79
+ result = conn.execute(
80
+ "MATCH (a:person) WHERE a.isStudent = $1 AND a.isWorker = $k RETURN COUNT(*)", {"1": False, "k": False}
81
+ )
82
+ assert result.has_next()
83
+ assert result.get_next() == [1]
84
+ assert not result.has_next()
85
+ result.close()
86
+
87
+
88
+ def test_int_param(conn_db_readonly: ConnDB) -> None:
89
+ conn, _ = conn_db_readonly
90
+ result = conn.execute("MATCH (a:person) WHERE a.age < $AGE RETURN COUNT(*)", {"AGE": 1})
91
+ assert result.has_next()
92
+ assert result.get_next() == [0]
93
+ assert not result.has_next()
94
+ result.close()
95
+
96
+
97
+ def test_double_param(conn_db_readonly: ConnDB) -> None:
98
+ conn, _ = conn_db_readonly
99
+ result = conn.execute("MATCH (a:person) WHERE a.eyeSight = $E RETURN COUNT(*)", {"E": 5.0})
100
+ assert result.has_next()
101
+ assert result.get_next() == [2]
102
+ assert not result.has_next()
103
+ result.close()
104
+
105
+
106
+ def test_str_param(conn_db_readonly: ConnDB) -> None:
107
+ conn, _ = conn_db_readonly
108
+ result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN concat(a.fName, $S);", {"S": "HH"})
109
+ assert result.has_next()
110
+ assert result.get_next() == ["AliceHH"]
111
+ assert not result.has_next()
112
+ result.close()
113
+
114
+
115
+ def test_date_param(conn_db_readonly: ConnDB) -> None:
116
+ conn, _ = conn_db_readonly
117
+ result = conn.execute("MATCH (a:person) WHERE a.birthdate = $1 RETURN COUNT(*);", {"1": datetime.date(1900, 1, 1)})
118
+ assert result.has_next()
119
+ assert result.get_next() == [2]
120
+ assert not result.has_next()
121
+ result.close()
122
+
123
+
124
+ def test_timestamp_param(conn_db_readonly: ConnDB) -> None:
125
+ conn, _ = conn_db_readonly
126
+ result = conn.execute(
127
+ "MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);",
128
+ {"1": datetime.datetime(2011, 8, 20, 11, 25, 30)},
129
+ )
130
+ assert result.has_next()
131
+ assert result.get_next() == [1]
132
+ assert not result.has_next()
133
+ result.close()
134
+
135
+
136
+ def test_int64_list_param(conn_db_readonly: ConnDB) -> None:
137
+ conn, _ = conn_db_readonly
138
+ result = conn.execute("MATCH (a:person {workedHours: $1}) RETURN COUNT(*);", {"1": [3, 4, 5, 6, 7]})
139
+ assert result.has_next()
140
+ assert result.get_next() == [1]
141
+ assert not result.has_next()
142
+ result.close()
143
+
144
+
145
+ def test_empty_list_param(conn_db_readonly: ConnDB) -> None:
146
+ conn, _ = conn_db_readonly
147
+ result = conn.execute("RETURN list_contains($list, $item)", {"list": [], "item": 5})
148
+ assert result.has_next()
149
+ assert result.get_next() == [False]
150
+ assert not result.has_next()
151
+ result.close()
152
+
153
+
154
+ def test_int64_list_list_param(conn_db_readonly: ConnDB) -> None:
155
+ conn, _ = conn_db_readonly
156
+ result = conn.execute(
157
+ "MATCH (a:person) WHERE a.courseScoresPerTerm = $1 OR a.courseScoresPerTerm = $2 RETURN COUNT(*);",
158
+ {"1": [[8, 10]], "2": [[7, 4], [8, 8], [9]]},
159
+ )
160
+ assert result.has_next()
161
+ assert result.get_next() == [2]
162
+ assert not result.has_next()
163
+ result.close()
164
+
165
+
166
+ def test_string_list_param(conn_db_readonly: ConnDB) -> None:
167
+ conn, _ = conn_db_readonly
168
+ result = conn.execute("MATCH (a:person {usedNames: $1}) RETURN COUNT(*);", {"1": ["Carmen", "Fred"]})
169
+ assert result.has_next()
170
+ assert result.get_next() == [1]
171
+ assert not result.has_next()
172
+ result.close()
173
+
174
+
175
+ def test_map_param(conn_db_empty: ConnDB) -> None:
176
+ conn, _ = conn_db_empty
177
+ conn.execute(
178
+ "CREATE NODE TABLE tab(id int64, mp MAP(double, int64), mp2 MAP(int64, double), mp3 MAP(string, string), mp4 MAP(string, string)[], primary key(id))"
179
+ )
180
+ result = conn.execute(
181
+ "MERGE (t:tab {id: 0, mp: $1, mp2: $2, mp3: $3, mp4: $4}) RETURN t.*",
182
+ {
183
+ "1": {"key": [1.0, 2, 2.2], "value": [5, 3, -1]},
184
+ "2": {"key": [5, 4, 0], "value": [-0.5, 0, 2.2]},
185
+ "3": {"key": ["a", "b", "c"], "value": [1, "2", "3"]},
186
+ "4": [{"key": ["a"], "value": ["b"]}],
187
+ },
188
+ )
189
+ assert result.has_next()
190
+ assert result.get_next() == [
191
+ 0,
192
+ {1.0: 5, 2.0: 3, 2.2: -1},
193
+ {5: -0.5, 4: -0.0, 0: 2.2},
194
+ {"a": "1", "b": "2", "c": "3"},
195
+ [{"a": "b"}],
196
+ ]
197
+ assert not result.has_next()
198
+ result.close()
199
+
200
+
201
+ def test_general_list_param(conn_db_empty: ConnDB) -> None:
202
+ conn, _ = conn_db_empty
203
+ conn.execute(
204
+ "CREATE NODE TABLE tab(id int64, lst1 BOOL[], lst2 DOUBLE[], lst3 TIMESTAMP[], lst4 DATE[], lst5 INTERVAL[], lst6 STRING[], PRIMARY KEY(id))"
205
+ )
206
+ lst1 = [True, False]
207
+ lst2 = [1.0, 2.0]
208
+ lst3 = [datetime.datetime(2019, 11, 12, 11, 25, 30), datetime.datetime(1987, 2, 15, 3, 0, 2)]
209
+ lst4 = [datetime.date(2019, 11, 12), datetime.date(1987, 2, 15)]
210
+ lst5 = [lst3[0] - lst3[1]]
211
+ lst6 = [1, "2", "3"]
212
+ lst6ToString = ["1", "2", "3"]
213
+ result = conn.execute(
214
+ "MERGE (t:tab {id: 0, lst1: $1, lst2: $2, lst3: $3, lst4: $4, lst5: $5, lst6: $6}) RETURN t.*",
215
+ {"1": lst1, "2": lst2, "3": lst3, "4": lst4, "5": lst5, "6": lst6},
216
+ )
217
+ assert result.has_next()
218
+ assert result.get_next() == [0, lst1, lst2, lst3, lst4, lst5, lst6ToString]
219
+ assert not result.has_next()
220
+ result.close()
221
+
222
+
223
+ def test_null_resolution(conn_db_empty: ConnDB) -> None:
224
+ conn, _ = conn_db_empty
225
+ conn.execute(
226
+ "CREATE NODE TABLE tab(id SERIAL, lst1 INT64[], mp1 MAP(STRING, STRING), "
227
+ "nest MAP(STRING, MAP(STRING, INT64))[], PRIMARY KEY(id))"
228
+ )
229
+ lst1 = [1, 2, 3, None]
230
+ mp1 = {"key": ["a", "b", "c", "o"], "value": ["x", "y", "z", None]}
231
+ nest = [
232
+ {"key": ["2"], "value": [{"key": ["foo", "bar"], "value": [1, 2]}]},
233
+ {"key": ["1"], "value": [{"key": [], "value": []}]},
234
+ ]
235
+ result = conn.execute("MERGE (t:tab {lst1: $1, mp1: $2, nest: $3}) RETURN t.*", {"1": lst1, "2": mp1, "3": nest})
236
+ assert result.has_next()
237
+ assert result.get_next() == [
238
+ 0,
239
+ lst1,
240
+ {"a": "x", "b": "y", "c": "z", "o": None},
241
+ [{"2": {"foo": 1, "bar": 2}}, {"1": {}}],
242
+ ]
243
+ assert not result.has_next()
244
+ result.close()
245
+
246
+
247
+ def test_param_error1(conn_db_readonly: ConnDB) -> None:
248
+ conn, _ = conn_db_readonly
249
+ with pytest.raises(RuntimeError, match="Parameter name must be of type string but got <class 'int'>"):
250
+ conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", {1: 1})
251
+
252
+
253
+ def test_param_error2(conn_db_readonly: ConnDB) -> None:
254
+ conn, _ = conn_db_readonly
255
+ with pytest.raises(RuntimeError, match="Parameters must be a dict"):
256
+ conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", ["asd"])
257
+
258
+
259
+ def test_param_error3(conn_db_readonly: ConnDB) -> None:
260
+ conn, _ = conn_db_readonly
261
+ with pytest.raises(RuntimeError, match="Parameters must be a dict"):
262
+ conn.execute("MATCH (a:person) WHERE a.registerTime = $1 RETURN COUNT(*);", [("asd", 1, 1)])
263
+
264
+
265
+ def test_param(conn_db_readwrite: ConnDB) -> None:
266
+ conn, _ = conn_db_readwrite
267
+ conn.execute("CREATE NODE TABLE NodeOne(id INT64, name STRING, PRIMARY KEY(id));")
268
+ conn.execute("CREATE NODE TABLE NodeTwo(id INT64, name STRING, PRIMARY KEY(id));")
269
+ conn.execute("CREATE Rel TABLE RelA(from NodeOne to NodeOne);")
270
+ conn.execute("CREATE Rel TABLE RelB(from NodeTwo to NodeOne, id int64, name String);")
271
+ conn.execute('CREATE (t: NodeOne {id:1, name: "Alice"});')
272
+ conn.execute('CREATE (t: NodeOne {id:2, name: "Jack"});')
273
+ conn.execute('CREATE (t: NodeTwo {id:3, name: "Bob"});')
274
+ result = conn.execute(
275
+ "MATCH (a:NodeOne { id: $a_id }),"
276
+ "(b:NodeTwo { id: $b_id }),"
277
+ "(c: NodeOne{ id: $c_id } )"
278
+ " MERGE"
279
+ " (a)-[:RelA]->(c),"
280
+ " (b)-[r:RelB { id: 2, name: $my_param }]->(c)"
281
+ " return r.*;",
282
+ {"a_id": 1, "b_id": 3, "c_id": 2, "my_param": None},
283
+ )
284
+ assert result.has_next()
285
+ assert result.get_next() == [2, None]
286
+ result.close()
287
+
288
+
289
+ def test_param_error4(conn_db_readonly: ConnDB) -> None:
290
+ conn, _ = conn_db_readonly
291
+ with pytest.raises(
292
+ RuntimeError,
293
+ match="Runtime exception: Cannot convert Python object to Lbug value : INT8 is incompatible with TIMESTAMP",
294
+ ):
295
+ conn.execute(
296
+ "MATCH (a:person {workedHours: $1}) RETURN COUNT(*);", {"1": [1, 2, datetime.datetime(2023, 3, 25)]}
297
+ )
298
+
299
+
300
+ def test_dict_conversion(conn_db_readwrite: ConnDB) -> None:
301
+ conn, _ = conn_db_readwrite
302
+ # Interpret as MAP.
303
+ result = conn.execute("RETURN $st", {"st": {"key": [1, 2, 3], "value": [3, 7, 98]}})
304
+ assert result.get_next() == [{1: 3, 2: 7, 3: 98}]
305
+ # Interpret as STRUCT since the first field name is not "key".
306
+ result = conn.execute("RETURN $st", {"st": {"key1": [1, 2, 3], "value": [3, 7, 98]}})
307
+ assert result.get_next() == [{"key1": [1, 2, 3], "value": [3, 7, 98]}]
308
+ # Interpret as STRUCT since the number of elements in key and value doesn't match.
309
+ result = conn.execute("RETURN $st", {"st": {"key": [1, 2], "value": [3, 7, 98, 4]}})
310
+ assert result.get_next() == [{"key": [1, 2], "value": [3, 7, 98, 4]}]
311
+
312
+
313
+ def test_null_handling(conn_db_readwrite: ConnDB) -> None:
314
+ conn, _ = conn_db_readwrite
315
+ result = conn.execute(
316
+ """
317
+ UNWIND $edges AS edge
318
+ WITH edge, size(edge.fact_embedding) AS score
319
+ ORDER BY score DESC
320
+ LIMIT $limit
321
+ RETURN edge.uuid;
322
+ """,
323
+ {
324
+ "edges": [
325
+ {
326
+ "uuid": "1c4e35a9-c6cb-4517-971f-37f209c71e64",
327
+ "fact_embedding": [
328
+ -0.010113425552845001,
329
+ -0.01922552101314068,
330
+ 0.007402684073895216,
331
+ ],
332
+ "expired_at": None,
333
+ }
334
+ ],
335
+ "limit": 10,
336
+ },
337
+ )
338
+ assert result.has_next()
339
+ result.get_next()[0] = "1c4e35a9-c6cb-4517-971f-37f209c71e64"
340
+ assert not result.has_next()
@@ -0,0 +1,117 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime
4
+ import uuid
5
+
6
+ import pytest
7
+ from type_aliases import ConnDB
8
+
9
+
10
+ def test_read(conn_db_readonly: ConnDB) -> None:
11
+ conn, _ = conn_db_readonly
12
+ prepared_query = "MATCH (a:person) WHERE a.isStudent = $1 AND a.isWorker = $k RETURN COUNT(*)"
13
+
14
+ result = conn.execute(prepared_query, {"1": False, "k": False})
15
+ assert result.has_next()
16
+ assert result.get_next() == [1]
17
+ assert not result.has_next()
18
+
19
+ result = conn.execute(prepared_query, {"1": True, "k": False})
20
+ assert result.has_next()
21
+ assert result.get_next() == [3]
22
+ assert not result.has_next()
23
+
24
+ result = conn.execute(prepared_query, {"1": False, "k": True})
25
+ assert result.has_next()
26
+ assert result.get_next() == [4]
27
+ assert not result.has_next()
28
+
29
+ result = conn.execute(prepared_query, {"1": True, "k": True})
30
+ assert result.has_next()
31
+ assert result.get_next() == [0]
32
+ assert not result.has_next()
33
+
34
+
35
+ def test_null_value(conn_db_readonly: ConnDB) -> None:
36
+ conn, _ = conn_db_readonly
37
+ prepared_query = "RETURN [4, $1, 2, $3, 4]"
38
+
39
+ result = conn.execute(prepared_query, {"1": None, "3": 5})
40
+ assert result.has_next()
41
+ assert result.get_next() == [[4, None, 2, 5, 4]]
42
+ assert not result.has_next()
43
+
44
+
45
+ def test_write(conn_db_readwrite: ConnDB) -> None:
46
+ conn, _ = conn_db_readwrite
47
+ orgs = [
48
+ {
49
+ "ID": 1001,
50
+ "name": "org1",
51
+ "orgCode": 1,
52
+ "mark": 1.0,
53
+ "score": 1,
54
+ "history": "history1",
55
+ "licenseValidInterval": datetime.timedelta(days=1),
56
+ "rating": 1.0,
57
+ },
58
+ {
59
+ "ID": 1002,
60
+ "name": "org2",
61
+ "orgCode": 2,
62
+ "mark": 2.0,
63
+ "score": 2,
64
+ "history": "history2",
65
+ "licenseValidInterval": datetime.timedelta(days=2),
66
+ "rating": 2.0,
67
+ },
68
+ {
69
+ "ID": 1003,
70
+ "name": "org3",
71
+ "orgCode": 3,
72
+ "mark": 3.0,
73
+ "score": 3,
74
+ "history": "history3",
75
+ "licenseValidInterval": datetime.timedelta(days=3),
76
+ "rating": 3.0,
77
+ },
78
+ ]
79
+
80
+ prepared_query = "CREATE (n:organisation {ID: $ID, name: $name, orgCode: $orgCode, mark: $mark, score: $score, history: $history, licenseValidInterval: $licenseValidInterval, rating: $rating})"
81
+ for org in orgs:
82
+ org_dict = {str(k): v for k, v in org.items()}
83
+ conn.execute(prepared_query, org_dict)
84
+
85
+ all_orgs_res = conn.execute("MATCH (n:organisation) RETURN n")
86
+ while all_orgs_res.has_next():
87
+ n = all_orgs_res.get_next()[0]
88
+ if n["ID"] not in [o["ID"] for o in orgs]:
89
+ continue
90
+ for expected_org in orgs:
91
+ if n["ID"] == expected_org["ID"]:
92
+ assert n["ID"] == expected_org["ID"]
93
+ assert n["name"] == expected_org["name"]
94
+ assert n["orgCode"] == expected_org["orgCode"]
95
+ assert n["mark"] == expected_org["mark"]
96
+ assert n["score"] == expected_org["score"]
97
+ assert n["history"] == expected_org["history"]
98
+ assert n["licenseValidInterval"] == expected_org["licenseValidInterval"]
99
+ assert n["rating"] == expected_org["rating"]
100
+ break
101
+
102
+ conn.execute("CREATE NODE TABLE uuid_table (id UUID, PRIMARY KEY(id));")
103
+ conn.execute("CREATE (:uuid_table {id: $1});", {"1": uuid.uuid5(uuid.NAMESPACE_DNS, "lbug")})
104
+ result = conn.execute("MATCH (n:uuid_table) RETURN n.id;")
105
+ assert result.get_next() == [uuid.uuid5(uuid.NAMESPACE_DNS, "lbug")]
106
+
107
+
108
+ def test_error(conn_db_readonly: ConnDB) -> None:
109
+ with pytest.raises(RuntimeError, match=r"Binder exception: Table dog does not exist."):
110
+ conn_db_readonly[0].execute("MATCH (d:dog) WHERE d.isServiceDog = $1 RETURN COUNT(*)")
111
+
112
+
113
+ def test_prepare_limit(conn_db_readonly: ConnDB) -> None:
114
+ result = conn_db_readonly[0].execute("MATCH (p:person) return p.ID limit $lt", {"lt": 3})
115
+ assert result.get_next() == [0]
116
+ assert result.get_next() == [2]
117
+ assert result.get_next() == [3]
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from type_aliases import ConnDB
4
+
5
+
6
+ def test_get_execution_time(conn_db_readonly: ConnDB) -> None:
7
+ conn, _ = conn_db_readonly
8
+ result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a")
9
+ assert result.get_execution_time() > 0
10
+ result.close()
11
+
12
+
13
+ def test_get_compiling_time(conn_db_readonly: ConnDB) -> None:
14
+ conn, _ = conn_db_readonly
15
+ result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a")
16
+ assert result.get_compiling_time() > 0
17
+ result.close()
18
+
19
+
20
+ def test_get_num_tuples(conn_db_readonly: ConnDB) -> None:
21
+ conn, _ = conn_db_readonly
22
+ result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a")
23
+ assert result.get_num_tuples() == 1
24
+ result.close()
25
+
26
+
27
+ def test_explain(conn_db_readonly: ConnDB) -> None:
28
+ conn, _ = conn_db_readonly
29
+ result = conn.execute("EXPLAIN MATCH (a:person) WHERE a.ID = 0 RETURN a")
30
+ assert result.get_num_tuples() == 1
31
+ result.close()
32
+
33
+
34
+ def test_context_manager(conn_db_readonly: ConnDB) -> None:
35
+ conn, _ = conn_db_readonly
36
+ with conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a") as result:
37
+ assert result.get_num_tuples() == 1
38
+ assert result.get_compiling_time() > 0
39
+
40
+ # context exit guarantees immediately 'close' of the underlying QueryResult
41
+ # (don't have to wait for __del__, which may not ever actually get called)
42
+ assert result.is_closed
43
+
44
+
45
+ def test_multiple_query_results(conn_db_readonly: ConnDB) -> None:
46
+ conn, _ = conn_db_readonly
47
+ results = conn.execute("RETURN 1; RETURN 2; RETURN 3;")
48
+ assert len(results) == 3
49
+ i = 1
50
+ for result in results:
51
+ assert result.get_num_tuples() == 1
52
+ assert result.has_next()
53
+ assert result.get_next() == [i]
54
+ i += 1
@@ -0,0 +1,44 @@
1
+ import subprocess
2
+ import sys
3
+ from pathlib import Path
4
+ from textwrap import dedent
5
+
6
+ from test_helper import LBUG_ROOT
7
+ from conftest import get_db_file_path
8
+
9
+
10
+ def test_query_result_close(tmp_path: Path, build_dir: Path) -> None:
11
+ db_path = get_db_file_path(tmp_path)
12
+ code = dedent(f"""
13
+ import sys
14
+ sys.path.append(r"{build_dir!s}")
15
+
16
+ import real_ladybug as lb
17
+ db = lb.Database(r"{db_path!s}")
18
+ conn = lb.Connection(db)
19
+ conn.execute('''
20
+ CREATE NODE TABLE person (
21
+ ID INT64,
22
+ fName STRING,
23
+ gender INT64,
24
+ isStudent BOOLEAN,
25
+ isWorker BOOLEAN,
26
+ age INT64,
27
+ eyeSight DOUBLE,
28
+ birthdate DATE,
29
+ registerTime TIMESTAMP,
30
+ lastJobDuration INTERVAL,
31
+ workedHours INT64[],
32
+ usedNames STRING[],
33
+ courseScoresPerTerm INT64[][],
34
+ grades INT64[4],
35
+ height float,
36
+ u UUID,
37
+ PRIMARY KEY (ID))
38
+ ''')
39
+ conn.execute('COPY person FROM "{LBUG_ROOT}/dataset/tinysnb/vPerson.csv" (HEADER=true)')
40
+ result = conn.execute("MATCH (a:person) WHERE a.ID = 0 RETURN a.isStudent;")
41
+ # result.close()
42
+ """)
43
+ result = subprocess.run([sys.executable, "-c", code])
44
+ assert result.returncode == 0