instaui 0.1.7__py3-none-any.whl → 0.1.9__py3-none-any.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.
- instaui/arco/components/calendar.py +1 -1
- instaui/arco/components/cascader.py +1 -1
- instaui/arco/static/instaui-arco.css +1 -1
- instaui/arco/static/instaui-arco.js +55771 -55771
- instaui/components/html/heading.py +8 -8
- instaui/components/html/input.py +4 -4
- instaui/components/html/label.py +2 -2
- instaui/components/html/li.py +1 -1
- instaui/components/html/number.py +5 -5
- instaui/components/html/paragraph.py +2 -2
- instaui/components/html/select.py +0 -5
- instaui/components/html/span.py +2 -2
- instaui/components/html/table.py +6 -6
- instaui/components/html/textarea.py +4 -4
- instaui/components/row.py +0 -3
- instaui/components/shiki_code/static/shiki-style.css +179 -179
- instaui/experimental/__init__.py +1 -2
- instaui/shadcn_classless/static/shadcn-classless.css +403 -403
- instaui/spa_router/_file_base_utils.py +20 -16
- instaui/static/insta-ui.esm-browser.prod.js +3672 -3663
- instaui/static/insta-ui.js.map +1 -1
- instaui/template/webview_template.py +0 -2
- instaui/ui/__init__.py +1 -1
- instaui/ui/__init__.pyi +1 -1
- instaui/vars/web_computed.py +6 -0
- instaui/webview/__init__.py +1 -0
- instaui/webview/index.py +0 -1
- {instaui-0.1.7.dist-info → instaui-0.1.9.dist-info}/METADATA +19 -26
- {instaui-0.1.7.dist-info → instaui-0.1.9.dist-info}/RECORD +63 -69
- {instaui-0.1.7.dist-info → instaui-0.1.9.dist-info}/WHEEL +1 -1
- instaui/experimental/link_sql/__init__.py +0 -3
- instaui/experimental/link_sql/_base.py +0 -23
- instaui/experimental/link_sql/_duckdb.py +0 -221
- instaui/experimental/link_sql/_types.py +0 -15
- instaui/experimental/link_sql/data_source.js +0 -50
- instaui/vars/__init__.py +0 -13
- {instaui-0.1.7.dist-info → instaui-0.1.9.dist-info/licenses}/LICENSE +0 -0
@@ -1,221 +0,0 @@
|
|
1
|
-
from pathlib import Path
|
2
|
-
from typing import Dict, TypeVar
|
3
|
-
import itertools
|
4
|
-
from instaui import ui, arco
|
5
|
-
from ._base import DataSourceElement
|
6
|
-
from ._types import TFilters, TQueryStrInfo
|
7
|
-
|
8
|
-
try:
|
9
|
-
import pandas
|
10
|
-
import duckdb
|
11
|
-
except ImportError as e:
|
12
|
-
raise e
|
13
|
-
|
14
|
-
|
15
|
-
TElementClass = TypeVar("TElementClass", bound=ui.element)
|
16
|
-
|
17
|
-
|
18
|
-
class DuckdbDataFrameSource:
|
19
|
-
QUERY_ID: int = 0
|
20
|
-
|
21
|
-
def __init__(
|
22
|
-
self,
|
23
|
-
table_name: str,
|
24
|
-
):
|
25
|
-
super().__init__()
|
26
|
-
|
27
|
-
self._element = DataSourceElement()
|
28
|
-
self._conn = duckdb.connect(":default:", read_only=False)
|
29
|
-
self._table_name = table_name
|
30
|
-
|
31
|
-
def _generate_query_id(self):
|
32
|
-
self.QUERY_ID += 1
|
33
|
-
return self.QUERY_ID
|
34
|
-
|
35
|
-
def __getitem__(self, field: str):
|
36
|
-
def use_fn(cls: type[TElementClass]) -> TElementClass:
|
37
|
-
if issubclass(cls, arco.select):
|
38
|
-
return self.__apply_select(field)(cls)
|
39
|
-
|
40
|
-
if issubclass(cls, arco.input):
|
41
|
-
return self.__apply_input(field)(cls)
|
42
|
-
|
43
|
-
raise NotImplementedError(f"Not supported component:{cls.__name__}")
|
44
|
-
|
45
|
-
return use_fn
|
46
|
-
|
47
|
-
def __query_distinct_field_values(
|
48
|
-
self, field: str, query_id: int, order_sql: str = ""
|
49
|
-
):
|
50
|
-
@ui.computed(inputs=[self.__query_str_info(field, query_id), field, order_sql])
|
51
|
-
def query_distinct_field_values_computed(
|
52
|
-
with_filters_info: TQueryStrInfo, field: str, order_sql: str
|
53
|
-
):
|
54
|
-
sql = f"with cte as ({with_filters_info['sql']}) select distinct {field} from cte {order_sql}"
|
55
|
-
|
56
|
-
local_con = self._conn.cursor()
|
57
|
-
|
58
|
-
query = local_con.sql(sql, params=with_filters_info["params"])
|
59
|
-
return list(itertools.chain(*query.fetchall()))
|
60
|
-
|
61
|
-
return query_distinct_field_values_computed
|
62
|
-
|
63
|
-
def __apply_select(self, field: str):
|
64
|
-
def use_fn(cls: type[arco.select]) -> arco.select:
|
65
|
-
query_id = self._generate_query_id()
|
66
|
-
element = cls(
|
67
|
-
self.__query_distinct_field_values(
|
68
|
-
field=field, query_id=query_id, order_sql=f"order by {field}"
|
69
|
-
)
|
70
|
-
)
|
71
|
-
|
72
|
-
on_change = ui.js_event(
|
73
|
-
inputs=[ui.event_context.e(), field, query_id],
|
74
|
-
outputs=[self._element._ele_ref],
|
75
|
-
code=r"""(value,field,query_id) => {
|
76
|
-
if (value) {
|
77
|
-
return {method: 'addFilter', args:[{field, expr: `${field}= ?`,value,query_id}]};
|
78
|
-
}
|
79
|
-
|
80
|
-
return {method:'removeFilter', args:[{field,query_id}]};
|
81
|
-
}""",
|
82
|
-
)
|
83
|
-
|
84
|
-
element.on_change(on_change)
|
85
|
-
|
86
|
-
return element
|
87
|
-
|
88
|
-
return use_fn
|
89
|
-
|
90
|
-
def __apply_input(self, field: str):
|
91
|
-
def use_fn(cls: type[arco.input]) -> arco.input:
|
92
|
-
query_id = self._generate_query_id()
|
93
|
-
element = cls()
|
94
|
-
|
95
|
-
on_change = ui.js_event(
|
96
|
-
inputs=[ui.event_context.e(), field, query_id],
|
97
|
-
outputs=[self._element._ele_ref],
|
98
|
-
code=r"""(value,field,query_id) => {
|
99
|
-
if (value) {
|
100
|
-
value = `%${value.trim()}%`
|
101
|
-
return {method: 'addFilter', args:[{field, expr: `${field} like ?`,value,replace:true,query_id}]};
|
102
|
-
}
|
103
|
-
|
104
|
-
return {method:'removeFilter', args:[{field,query_id}]};
|
105
|
-
}""",
|
106
|
-
)
|
107
|
-
|
108
|
-
element.on_input(on_change)
|
109
|
-
|
110
|
-
return element
|
111
|
-
|
112
|
-
return use_fn
|
113
|
-
|
114
|
-
def __query_str_info(self, target_field: str = "", query_id: int = -1):
|
115
|
-
@ui.computed(inputs=[self._element.filters, target_field, query_id])
|
116
|
-
def query_str_computed(filters: TFilters, target_field: str, query_id: int):
|
117
|
-
if not filters:
|
118
|
-
return {
|
119
|
-
"sql": f"select * from {self._table_name}",
|
120
|
-
"params": [],
|
121
|
-
}
|
122
|
-
else:
|
123
|
-
filter_exprs = []
|
124
|
-
|
125
|
-
if target_field:
|
126
|
-
target_key = f"{target_field}-{query_id}"
|
127
|
-
without_target_exprs = (
|
128
|
-
exprs for key, exprs in filters.items() if key != target_key
|
129
|
-
)
|
130
|
-
filter_exprs = list(itertools.chain(*without_target_exprs))
|
131
|
-
else:
|
132
|
-
filter_exprs = list(itertools.chain(*filters.values()))
|
133
|
-
|
134
|
-
where_stem = " and ".join(info["expr"] for info in filter_exprs)
|
135
|
-
if where_stem:
|
136
|
-
where_stem = f" where {where_stem}"
|
137
|
-
return {
|
138
|
-
"sql": f"select * from {self._table_name}{where_stem}",
|
139
|
-
"params": [info["value"] for info in filter_exprs],
|
140
|
-
}
|
141
|
-
|
142
|
-
return query_str_computed
|
143
|
-
|
144
|
-
def query_str(self):
|
145
|
-
return ui.js_computed(
|
146
|
-
inputs=[self.__query_str_info()],
|
147
|
-
code=r"""info=>{
|
148
|
-
const {sql,params} = info;
|
149
|
-
let currentIndex = 0;
|
150
|
-
return sql.replace(/\?/g, function () {
|
151
|
-
if (currentIndex >= params.length) {
|
152
|
-
throw new Error('Not enough parameters provided for the SQL statement.');
|
153
|
-
}
|
154
|
-
return JSON.stringify(params[currentIndex++]);
|
155
|
-
});
|
156
|
-
}""",
|
157
|
-
)
|
158
|
-
|
159
|
-
def filters(self):
|
160
|
-
return self._element.filters
|
161
|
-
|
162
|
-
def __apply_table(self, *, sql: str):
|
163
|
-
def use_fn(cls: type[arco.table]) -> arco.table:
|
164
|
-
@ui.computed(inputs=[self.__query_str_info(), sql])
|
165
|
-
def table_query(with_filters_into: TQueryStrInfo, sql: str):
|
166
|
-
sql = f"with cte as ({with_filters_into['sql']}) {sql}"
|
167
|
-
|
168
|
-
local_con = self._conn.cursor()
|
169
|
-
|
170
|
-
query = local_con.sql(sql, params=with_filters_into["params"])
|
171
|
-
columns = query.columns
|
172
|
-
values = query.fetchall()
|
173
|
-
|
174
|
-
real_cols = [{"title": col, "dataIndex": col} for col in columns]
|
175
|
-
|
176
|
-
real_values = [
|
177
|
-
{col: val for col, val in zip(columns, row)} for row in values
|
178
|
-
]
|
179
|
-
|
180
|
-
return {
|
181
|
-
"columns": real_cols,
|
182
|
-
"data": real_values,
|
183
|
-
}
|
184
|
-
|
185
|
-
element = cls(
|
186
|
-
data=ui.js_computed(inputs=[table_query], code=r"v=> v ? v.data : []"),
|
187
|
-
columns=ui.js_computed(
|
188
|
-
inputs=[table_query], code=r"v=> v ? v.columns : []"
|
189
|
-
),
|
190
|
-
)
|
191
|
-
|
192
|
-
return element
|
193
|
-
|
194
|
-
return use_fn
|
195
|
-
|
196
|
-
def __call__(self, cls: type[arco.table], *, sql: str = "select * from cte"):
|
197
|
-
return self.__apply_table(sql=sql)(cls)
|
198
|
-
|
199
|
-
def query_table(self, *, sql: str):
|
200
|
-
return self.__apply_table(sql=sql)
|
201
|
-
|
202
|
-
|
203
|
-
class Facade:
|
204
|
-
def __call__(self, db: Path):
|
205
|
-
self.db = db
|
206
|
-
raise NotImplementedError()
|
207
|
-
|
208
|
-
@classmethod
|
209
|
-
def from_pandas(
|
210
|
-
cls, dataframe: "pandas.DataFrame", *, table_name: str = "df"
|
211
|
-
) -> DuckdbDataFrameSource:
|
212
|
-
ds = DuckdbDataFrameSource(table_name)
|
213
|
-
|
214
|
-
cursor = ds._conn.cursor()
|
215
|
-
cursor.execute(
|
216
|
-
f"create table if not exists {table_name} as select * from dataframe"
|
217
|
-
)
|
218
|
-
return ds
|
219
|
-
|
220
|
-
|
221
|
-
_facade = Facade()
|
@@ -1,15 +0,0 @@
|
|
1
|
-
from typing import Any, Dict, List
|
2
|
-
from typing_extensions import TypedDict
|
3
|
-
|
4
|
-
|
5
|
-
class TFilterInfo(TypedDict):
|
6
|
-
expr: str
|
7
|
-
value: Any
|
8
|
-
|
9
|
-
|
10
|
-
TFilters = Dict[str, List[TFilterInfo]]
|
11
|
-
|
12
|
-
|
13
|
-
class TQueryStrInfo(TypedDict):
|
14
|
-
sql: str
|
15
|
-
params: List[Any]
|
@@ -1,50 +0,0 @@
|
|
1
|
-
|
2
|
-
export default {
|
3
|
-
props: [],
|
4
|
-
|
5
|
-
setup(props, { emit, expose }) {
|
6
|
-
const filters = new Map()
|
7
|
-
|
8
|
-
function addFilter(filter) {
|
9
|
-
const { field, expr, value, replace = true, query_id } = filter
|
10
|
-
const key = `${field}-${query_id}`
|
11
|
-
|
12
|
-
if (!filters.has(key)) {
|
13
|
-
filters.set(key, [])
|
14
|
-
}
|
15
|
-
|
16
|
-
const info = { expr, value }
|
17
|
-
|
18
|
-
if (replace) {
|
19
|
-
filters.set(key, [info])
|
20
|
-
} else {
|
21
|
-
filters.get(key).push(info)
|
22
|
-
}
|
23
|
-
emit("filter-changed", { filters: Object.fromEntries(filters.entries()), target: field, query_id })
|
24
|
-
}
|
25
|
-
|
26
|
-
function removeFilter(info) {
|
27
|
-
const { field, query_id } = info
|
28
|
-
const key = `${field}-${query_id}`
|
29
|
-
|
30
|
-
filters.delete(key)
|
31
|
-
emit("filter-changed", { filters: Object.fromEntries(filters.entries()), target: field, query_id })
|
32
|
-
}
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
function test(count) {
|
37
|
-
console.log('test', count)
|
38
|
-
}
|
39
|
-
|
40
|
-
expose({
|
41
|
-
test,
|
42
|
-
addFilter,
|
43
|
-
removeFilter,
|
44
|
-
})
|
45
|
-
|
46
|
-
|
47
|
-
},
|
48
|
-
|
49
|
-
|
50
|
-
}
|
instaui/vars/__init__.py
DELETED
File without changes
|