jupyter-duckdb 1.2.101__tar.gz → 1.2.102__tar.gz
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.
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/PKG-INFO +1 -1
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/setup.py +4 -2
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/kernel.py +72 -54
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/visualization/Plotly.py +8 -18
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/visualization/RATreeDrawer.py +34 -2
- jupyter_duckdb-1.2.102/src/duckdb_kernel/visualization/lib/__init__.py +53 -0
- jupyter_duckdb-1.2.102/src/duckdb_kernel/visualization/lib/plotly-3.0.1.min.js +3879 -0
- jupyter_duckdb-1.2.102/src/duckdb_kernel/visualization/lib/ra.css +3 -0
- jupyter_duckdb-1.2.102/src/duckdb_kernel/visualization/lib/ra.js +55 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/jupyter_duckdb.egg-info/PKG-INFO +1 -1
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/jupyter_duckdb.egg-info/SOURCES.txt +4 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/README.md +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/setup.cfg +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/__main__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/Column.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/Connection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/Constraint.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/DatabaseError.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/ForeignKey.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/Table.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/error/EmptyResultError.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/error/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/duckdb/Connection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/duckdb/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/postgres/Connection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/postgres/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/postgres/util.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/sqlite/Connection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/db/implementation/sqlite/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/kernel.json +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/magics/MagicCommand.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/magics/MagicCommandCallback.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/magics/MagicCommandException.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/magics/MagicCommandHandler.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/magics/StringWrapper.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/magics/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/DCParser.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/LogicParser.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/ParserError.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/RAParser.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/DCOperand.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/LogicElement.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/LogicOperand.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/LogicOperator.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/RABinaryOperator.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/RAElement.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/RAOperand.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/RAOperator.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/RAUnaryOperator.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Add.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/And.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/ArrowLeft.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/ConditionalSet.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Cross.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Difference.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Divide.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Division.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Equal.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/FullOuterJoin.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/GreaterThan.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/GreaterThanEqual.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Intersection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Join.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/LeftOuterJoin.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/LessThan.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/LessThanEqual.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Minus.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Multiply.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Or.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/RightOuterJoin.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Unequal.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/Union.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/binary/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/unary/Not.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/unary/Projection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/unary/Rename.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/unary/Selection.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/elements/unary/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/tokenizer/Token.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/tokenizer/Tokenizer.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/tokenizer/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/util/RenamableColumn.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/util/RenamableColumnList.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/parser/util/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/tests/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/tests/test_dc.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/tests/test_ra.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/tests/test_result_comparison.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/tests/test_sql.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/util/ResultSetComparator.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/util/SQL.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/util/TestError.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/util/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/util/formatting.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/visualization/Drawer.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/visualization/SchemaDrawer.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/visualization/__init__.py +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/jupyter_duckdb.egg-info/dependency_links.txt +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/jupyter_duckdb.egg-info/requires.txt +0 -0
- {jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/jupyter_duckdb.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
3
|
# configuration
|
|
4
|
-
PACKAGE_VERSION = '1.2.
|
|
4
|
+
PACKAGE_VERSION = '1.2.102'
|
|
5
5
|
DUCKDB_VERSION = '1.2.1'
|
|
6
6
|
|
|
7
7
|
DEPENDENCIES = [
|
|
@@ -46,7 +46,9 @@ if __name__ == '__main__':
|
|
|
46
46
|
include_package_data=True,
|
|
47
47
|
package_data={
|
|
48
48
|
'duckdb_kernel': [
|
|
49
|
-
'kernel.json'
|
|
49
|
+
'kernel.json',
|
|
50
|
+
'visualization/lib/*.css',
|
|
51
|
+
'visualization/lib/*.js',
|
|
50
52
|
]
|
|
51
53
|
}
|
|
52
54
|
)
|
|
@@ -10,6 +10,7 @@ from typing import Optional, Dict, List, Tuple
|
|
|
10
10
|
from ipykernel.kernelbase import Kernel
|
|
11
11
|
|
|
12
12
|
from .db import Connection, DatabaseError, Table
|
|
13
|
+
from .visualization.lib import *
|
|
13
14
|
from .db.error import *
|
|
14
15
|
from .magics import *
|
|
15
16
|
from .parser import RAParser, DCParser, ParserError
|
|
@@ -118,6 +119,7 @@ class DuckDBKernel(Kernel):
|
|
|
118
119
|
self._db = Postgres(host, port, username, password, database_name)
|
|
119
120
|
except ImportError:
|
|
120
121
|
self.print('psycopg could not be found', name='stderr')
|
|
122
|
+
return False
|
|
121
123
|
|
|
122
124
|
# Otherwise the provided path is used to create an
|
|
123
125
|
# in-process instance.
|
|
@@ -147,7 +149,7 @@ class DuckDBKernel(Kernel):
|
|
|
147
149
|
else:
|
|
148
150
|
return False
|
|
149
151
|
|
|
150
|
-
def _execute_stmt(self, query: str, silent: bool,
|
|
152
|
+
def _execute_stmt(self, name: str, query: str, silent: bool,
|
|
151
153
|
column_name_mapping: Dict[str, str],
|
|
152
154
|
max_rows: Optional[int]) -> Tuple[Optional[List[str]], Optional[List[List]]]:
|
|
153
155
|
if self._db is None:
|
|
@@ -163,52 +165,57 @@ class DuckDBKernel(Kernel):
|
|
|
163
165
|
|
|
164
166
|
et = time.time()
|
|
165
167
|
|
|
166
|
-
#
|
|
167
|
-
if silent:
|
|
168
|
-
|
|
168
|
+
# print result if not silent
|
|
169
|
+
if not silent:
|
|
170
|
+
# print EXPLAIN queries as raw text if using DuckDB
|
|
171
|
+
if query.strip().startswith('EXPLAIN') and self._db.plain_explain():
|
|
172
|
+
for ekey, evalue in rows:
|
|
173
|
+
html = f'<b>{ekey}</b><br><pre>{evalue}</pre>'
|
|
174
|
+
break
|
|
169
175
|
|
|
170
|
-
|
|
171
|
-
if query.strip().startswith('EXPLAIN') and self._db.plain_explain():
|
|
172
|
-
for ekey, evalue in rows:
|
|
173
|
-
self.print_data(f'<b>{ekey}</b><br><pre>{evalue}</pre>')
|
|
176
|
+
return None, None
|
|
174
177
|
|
|
175
|
-
|
|
178
|
+
# print every other query as a table
|
|
179
|
+
else:
|
|
180
|
+
if columns is not None:
|
|
181
|
+
# table header
|
|
182
|
+
mapped_columns = (column_name_mapping.get(c, c) for c in columns)
|
|
183
|
+
table_header = ''.join(f'<th>{c}</th>' for c in mapped_columns)
|
|
184
|
+
|
|
185
|
+
# table data
|
|
186
|
+
if max_rows is not None and len(rows) > max_rows:
|
|
187
|
+
table_data = f'''
|
|
188
|
+
{rows_table(rows[:math.ceil(max_rows / 2)])}
|
|
189
|
+
<tr>
|
|
190
|
+
<td colspan="{len(columns)}"
|
|
191
|
+
style="text-align: center"
|
|
192
|
+
title="{row_count(len(rows) - max_rows)} omitted">
|
|
193
|
+
...
|
|
194
|
+
</td>
|
|
195
|
+
</tr>
|
|
196
|
+
{rows_table(rows[-math.floor(max_rows // 2):])}
|
|
197
|
+
'''
|
|
198
|
+
else:
|
|
199
|
+
table_data = rows_table(rows)
|
|
200
|
+
|
|
201
|
+
# send to client
|
|
202
|
+
html = (f'''
|
|
203
|
+
<table class="duckdb-query-result-table">
|
|
204
|
+
{table_header}
|
|
205
|
+
{table_data}
|
|
206
|
+
</table>
|
|
207
|
+
|
|
208
|
+
{row_count(len(rows))} in {et - st:.3f}s
|
|
209
|
+
''')
|
|
176
210
|
|
|
177
|
-
# print every other query as a table
|
|
178
|
-
else:
|
|
179
|
-
if columns is not None:
|
|
180
|
-
# table header
|
|
181
|
-
mapped_columns = (column_name_mapping.get(c, c) for c in columns)
|
|
182
|
-
table_header = ''.join(f'<th>{c}</th>' for c in mapped_columns)
|
|
183
|
-
|
|
184
|
-
# table data
|
|
185
|
-
if max_rows is not None and len(rows) > max_rows:
|
|
186
|
-
table_data = f'''
|
|
187
|
-
{rows_table(rows[:math.ceil(max_rows / 2)])}
|
|
188
|
-
<tr>
|
|
189
|
-
<td colspan="{len(columns)}"
|
|
190
|
-
style="text-align: center"
|
|
191
|
-
title="{row_count(len(rows) - max_rows)} omitted">
|
|
192
|
-
...
|
|
193
|
-
</td>
|
|
194
|
-
</tr>
|
|
195
|
-
{rows_table(rows[-math.floor(max_rows // 2):])}
|
|
196
|
-
'''
|
|
197
211
|
else:
|
|
198
|
-
|
|
212
|
+
html = f'statement executed without result in {et - st:.3f}s'
|
|
199
213
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
</table>
|
|
206
|
-
''')
|
|
207
|
-
|
|
208
|
-
self.print_data(f'{row_count(len(rows))} in {et - st:.3f}s')
|
|
209
|
-
|
|
210
|
-
else:
|
|
211
|
-
self.print_data(f'statement executed without result in {et - st:.3f}s')
|
|
214
|
+
self.print_data(f'''
|
|
215
|
+
<div class="duckdb-query-result {name}">
|
|
216
|
+
{html}
|
|
217
|
+
</div>
|
|
218
|
+
''')
|
|
212
219
|
|
|
213
220
|
return columns, rows
|
|
214
221
|
|
|
@@ -498,16 +505,23 @@ class DuckDBKernel(Kernel):
|
|
|
498
505
|
# create and show visualization
|
|
499
506
|
if analyze:
|
|
500
507
|
vd = RATreeDrawer(self._db, root_node, tables)
|
|
501
|
-
svg = vd.
|
|
502
|
-
|
|
503
|
-
|
|
508
|
+
svg = vd.to_interactive_svg()
|
|
509
|
+
data = {
|
|
510
|
+
'generated_code': {
|
|
511
|
+
node_id: node.to_sql_with_renamed_columns(tables)
|
|
512
|
+
for node_id, node in vd.nodes.items()
|
|
513
|
+
}
|
|
514
|
+
}
|
|
504
515
|
|
|
505
|
-
|
|
506
|
-
|
|
516
|
+
else:
|
|
517
|
+
svg = ''
|
|
518
|
+
data = {
|
|
519
|
+
'generated_code': root_node.to_sql_with_renamed_columns(tables)
|
|
520
|
+
}
|
|
507
521
|
|
|
508
|
-
return
|
|
509
|
-
|
|
510
|
-
|
|
522
|
+
# return data
|
|
523
|
+
self.print_data(svg)
|
|
524
|
+
return data
|
|
511
525
|
|
|
512
526
|
def _all_ra_magic(self, silent: bool, value: str):
|
|
513
527
|
if value.lower() in ('1', 'on', 'true'):
|
|
@@ -689,10 +703,14 @@ class DuckDBKernel(Kernel):
|
|
|
689
703
|
execution_args['column_name_mapping'] = {}
|
|
690
704
|
|
|
691
705
|
# execute statement if needed
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
706
|
+
cols, rows = None, None
|
|
707
|
+
|
|
708
|
+
if not isinstance(clean_code, dict):
|
|
709
|
+
clean_code = {'default': clean_code}
|
|
710
|
+
|
|
711
|
+
for name, code in clean_code.items():
|
|
712
|
+
if code.strip():
|
|
713
|
+
cols, rows = self._execute_stmt(name, code, silent, **execution_args)
|
|
696
714
|
|
|
697
715
|
# execute magic command here if it does depend on query results
|
|
698
716
|
for callback in post_query_callbacks:
|
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
from decimal import Decimal
|
|
2
|
-
|
|
3
|
-
PLOTLY_VERSION = '3.0.1'
|
|
4
|
-
|
|
5
1
|
import json
|
|
6
|
-
from
|
|
2
|
+
from decimal import Decimal
|
|
7
3
|
from typing import Dict, List, Optional
|
|
4
|
+
from uuid import uuid4
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def __init() -> str:
|
|
13
|
-
global __PLOTLY_INITIALIZED
|
|
14
|
-
|
|
15
|
-
if not __PLOTLY_INITIALIZED:
|
|
16
|
-
__PLOTLY_INITIALIZED = True
|
|
17
|
-
return f'<script src="https://cdn.plot.ly/plotly-{PLOTLY_VERSION}.min.js"></script>'
|
|
18
|
-
else:
|
|
19
|
-
return ''
|
|
6
|
+
from .lib import init_plotly
|
|
20
7
|
|
|
21
8
|
|
|
22
9
|
def __div_id() -> str:
|
|
@@ -60,7 +47,7 @@ def __fix_decimal(x: List):
|
|
|
60
47
|
|
|
61
48
|
|
|
62
49
|
def draw_chart(title: Optional[str], traces: List[Dict] | Dict) -> str:
|
|
63
|
-
init =
|
|
50
|
+
init = init_plotly()
|
|
64
51
|
div_id = __div_id()
|
|
65
52
|
layout = __layout(title)
|
|
66
53
|
config = __config()
|
|
@@ -69,7 +56,10 @@ def draw_chart(title: Optional[str], traces: List[Dict] | Dict) -> str:
|
|
|
69
56
|
traces = json.dumps(traces)
|
|
70
57
|
|
|
71
58
|
return f'''
|
|
72
|
-
|
|
59
|
+
<script type="text/javascript">
|
|
60
|
+
{init}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
73
63
|
<div id="{div_id}"></div>
|
|
74
64
|
<script type="text/javascript">
|
|
75
65
|
Plotly.newPlot('{div_id}', {traces}, {json.dumps(layout)}, {json.dumps(config)});
|
{jupyter_duckdb-1.2.101 → jupyter_duckdb-1.2.102}/src/duckdb_kernel/visualization/RATreeDrawer.py
RENAMED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
from typing import Dict
|
|
1
|
+
from typing import Dict, Optional
|
|
2
2
|
|
|
3
3
|
from graphviz import Digraph
|
|
4
|
+
from uuid import uuid4
|
|
4
5
|
|
|
5
6
|
from duckdb_kernel.db import Table
|
|
6
7
|
from duckdb_kernel.parser.elements import RAElement
|
|
7
8
|
from duckdb_kernel.util.formatting import row_count
|
|
8
9
|
from .Drawer import Drawer
|
|
9
10
|
from ..db import Connection
|
|
11
|
+
from .lib import *
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class RATreeDrawer(Drawer):
|
|
@@ -15,6 +17,9 @@ class RATreeDrawer(Drawer):
|
|
|
15
17
|
self.root_node: RAElement = root_node
|
|
16
18
|
self.tables: Dict[str, Table] = tables
|
|
17
19
|
|
|
20
|
+
self.nodes: Dict[str, RAElement] = {}
|
|
21
|
+
self.root_node_id: Optional[str] = None
|
|
22
|
+
|
|
18
23
|
def to_graph(self) -> Digraph:
|
|
19
24
|
# create graph
|
|
20
25
|
ps = Digraph('Schema',
|
|
@@ -31,7 +36,11 @@ class RATreeDrawer(Drawer):
|
|
|
31
36
|
|
|
32
37
|
def __add_node(self, ps: Digraph, node: RAElement) -> str:
|
|
33
38
|
# use id of node object as identifier
|
|
34
|
-
node_id = f'node_{
|
|
39
|
+
node_id = f'node_{str(uuid4()).replace("-", "_")}'
|
|
40
|
+
|
|
41
|
+
self.nodes[node_id] = node
|
|
42
|
+
if node == self.root_node:
|
|
43
|
+
self.root_node_id = node_id
|
|
35
44
|
|
|
36
45
|
# generate child nodes
|
|
37
46
|
child_ids = [self.__add_node(ps, child) for child in node.children]
|
|
@@ -69,3 +78,26 @@ class RATreeDrawer(Drawer):
|
|
|
69
78
|
|
|
70
79
|
# return node identifier to generate edges
|
|
71
80
|
return node_id
|
|
81
|
+
|
|
82
|
+
def to_interactive_svg(self) -> str:
|
|
83
|
+
div_id = f'div-{str(uuid4())}'
|
|
84
|
+
|
|
85
|
+
css = init_css()
|
|
86
|
+
ra = init_ra()
|
|
87
|
+
svg = self.to_svg(True)
|
|
88
|
+
|
|
89
|
+
return f'''
|
|
90
|
+
<style type="text/css">
|
|
91
|
+
{css}
|
|
92
|
+
</style>
|
|
93
|
+
|
|
94
|
+
<div id="{div_id}">
|
|
95
|
+
{svg}
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<script type="text/javascript">
|
|
99
|
+
{ra}
|
|
100
|
+
|
|
101
|
+
animate_ra('{div_id}', '{self.root_node_id}')
|
|
102
|
+
</script>
|
|
103
|
+
'''
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
__CSS_INITIALIZED = False
|
|
4
|
+
__RA_INITIALIZED = False
|
|
5
|
+
__PLOTLY_INITIALIZED = False
|
|
6
|
+
|
|
7
|
+
__location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def init_css() -> str:
|
|
11
|
+
global __CSS_INITIALIZED
|
|
12
|
+
|
|
13
|
+
if not __CSS_INITIALIZED:
|
|
14
|
+
with open(os.path.join(__location, 'ra.css')) as ra_file:
|
|
15
|
+
css = ra_file.read()
|
|
16
|
+
else:
|
|
17
|
+
css = ''
|
|
18
|
+
|
|
19
|
+
__CSS_INITIALIZED = True
|
|
20
|
+
return css
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def init_ra() -> str:
|
|
24
|
+
global __RA_INITIALIZED
|
|
25
|
+
|
|
26
|
+
if not __RA_INITIALIZED:
|
|
27
|
+
with open(os.path.join(__location, 'ra.js')) as ra_file:
|
|
28
|
+
ra = ra_file.read()
|
|
29
|
+
else:
|
|
30
|
+
ra = ''
|
|
31
|
+
|
|
32
|
+
__RA_INITIALIZED = True
|
|
33
|
+
return ra
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def init_plotly() -> str:
|
|
37
|
+
global __PLOTLY_INITIALIZED
|
|
38
|
+
|
|
39
|
+
if not __PLOTLY_INITIALIZED:
|
|
40
|
+
with open(os.path.join(__location, 'plotly-3.0.1.min.js')) as plotly_file:
|
|
41
|
+
plotly = plotly_file.read()
|
|
42
|
+
else:
|
|
43
|
+
plotly = ''
|
|
44
|
+
|
|
45
|
+
__PLOTLY_INITIALIZED = True
|
|
46
|
+
return plotly
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
__all__ = [
|
|
50
|
+
'init_css',
|
|
51
|
+
'init_ra',
|
|
52
|
+
'init_plotly',
|
|
53
|
+
]
|