Skip to content

Commit cfc5cd3

Browse files
authored
Merge pull request #2854 from finos/misc-fixes
Fix empty Arrow `Table` constructor
2 parents 6d65d5f + 3e772ec commit cfc5cd3

File tree

9 files changed

+77
-66
lines changed

9 files changed

+77
-66
lines changed

cpp/perspective/src/cpp/arrow_loader.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ load_file(
7777
} else {
7878
std::shared_ptr<arrow::ipc::RecordBatchFileReader> batch_reader =
7979
*status;
80+
8081
std::vector<std::shared_ptr<arrow::RecordBatch>> batches;
8182
auto num_batches = batch_reader->num_record_batches();
8283
for (int i = 0; i < num_batches; ++i) {
83-
8484
auto status2 = batch_reader->ReadRecordBatch(i);
8585
if (!status2.ok()) {
8686
PSP_COMPLAIN_AND_ABORT(
@@ -91,7 +91,10 @@ load_file(
9191
std::shared_ptr<arrow::RecordBatch> chunk = *status2;
9292
batches.push_back(chunk);
9393
}
94-
auto status3 = arrow::Table::FromRecordBatches(batches);
94+
95+
auto status3 =
96+
arrow::Table::FromRecordBatches(batch_reader->schema(), batches);
97+
9598
if (!status3.ok()) {
9699
std::stringstream ss;
97100
ss << "Failed to create Table from RecordBatches: "

docs/src/components/DocItem/browser.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
1111
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
1212

13-
import "@finos/perspective-viewer";
14-
import "@finos/perspective-viewer-datagrid";
1513
import { SUPERSTORE_TABLE } from "@site/src/data/superstore.js";
1614

1715
export async function main(colorMode) {
16+
await import("@finos/perspective-viewer", { type: "module" });
17+
await import("@finos/perspective-viewer-datagrid");
18+
1819
await customElements.whenDefined("perspective-viewer");
1920
const viewers = document.querySelectorAll(
2021
"perspective-viewer:not(.nosuperstore)"

examples/blocks/src/raycasting/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ for (var j := 0; j <= radialSegments; j += 1) {
5555
vs[i0] := vs[i0] * bcos - vs[i0 + 2] * bsin;
5656
vs[i0 + 2] := b * bsin + vs[i0 + 2] * bcos;
5757
}
58-
}
58+
};
5959
6060
// Render scene
6161
var scale := resolution / (tan(fov / 2) * 400);

packages/perspective-esbuild-plugin/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ const { WorkerPlugin } = require("./worker.js");
1616
exports.PerspectiveEsbuildPlugin = function PerspectiveEsbuildPlugin(
1717
options = {}
1818
) {
19-
const wasm_plugin = WasmPlugin(!!options.wasm?.inline);
19+
const wasm_plugin = WasmPlugin(
20+
!!options.wasm?.inline,
21+
!options.wasm?.webpack_hack
22+
);
23+
2024
const worker_plugin = WorkerPlugin({
2125
targetdir: options.worker?.targetdir,
2226
});

packages/perspective-esbuild-plugin/wasm.js

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
const fs = require("fs");
1414
const path = require("path");
1515

16-
exports.WasmPlugin = function WasmPlugin(inline) {
16+
exports.WasmPlugin = function WasmPlugin(inline, webpack_hack) {
1717
function setup(build) {
1818
const options = build.initialOptions;
1919
options.metafile = true;
@@ -62,12 +62,14 @@ exports.WasmPlugin = function WasmPlugin(inline) {
6262
.toString()
6363
.slice(2)}__`;
6464
KEYSET.push(key);
65+
const url = webpack_hack ? `${key}(wasm)` : `wasm`;
66+
6567
return {
6668
pluginData: args.pluginData,
6769
contents: `
6870
import wasm from ${JSON.stringify(args.path)};
6971
export default function() {
70-
return fetch(new URL(${key}(wasm), import.meta.url));
72+
return fetch(new URL(${url}, import.meta.url));
7173
};
7274
`,
7375
};
@@ -84,39 +86,42 @@ exports.WasmPlugin = function WasmPlugin(inline) {
8486
});
8587

8688
build.onEnd(({ metafile }) => {
87-
for (const file of Object.keys(metafile.outputs)) {
88-
if (file.endsWith(".js")) {
89-
let contents = fs.readFileSync(file).toString();
90-
let updated = false;
91-
for (const key of KEYSET) {
92-
const symbol = contents.match(
93-
new RegExp(`${key}\\(([a-zA-Z0-9_\$]+?)\\)`)
94-
);
95-
96-
if (symbol?.[1]) {
97-
updated = true;
98-
const escapedSymbol = symbol[1].replace(
99-
/\$/g,
100-
"\\$"
101-
);
102-
const filename = contents.match(
103-
new RegExp(
104-
`${escapedSymbol}\\s*?=\\s*?\\"(.+?)\\"`
105-
)
89+
if (webpack_hack) {
90+
for (const file of Object.keys(metafile.outputs)) {
91+
if (file.endsWith(".js")) {
92+
let contents = fs.readFileSync(file).toString();
93+
let updated = false;
94+
for (const key of KEYSET) {
95+
const symbol = contents.match(
96+
new RegExp(`${key}\\(([a-zA-Z0-9_\$]+?)\\)`)
10697
);
10798

108-
contents = contents.replace(
109-
new RegExp(
110-
`${key}\\(([a-zA-Z0-9_\$]+?)\\)`,
111-
"g"
112-
),
113-
`"${filename[1]}"`
114-
);
99+
if (symbol?.[1]) {
100+
updated = true;
101+
const escapedSymbol = symbol[1].replace(
102+
/\$/g,
103+
"\\$"
104+
);
105+
106+
const filename = contents.match(
107+
new RegExp(
108+
`(?<![a-zA-Z0-9_\$])${escapedSymbol}\\s*?=\\s*?\\"(.+?)\\"`
109+
)
110+
);
111+
112+
contents = contents.replace(
113+
new RegExp(
114+
`${key}\\(([a-zA-Z0-9_\$]+?)\\)`,
115+
"g"
116+
),
117+
`"${filename[1]}"`
118+
);
119+
}
115120
}
116-
}
117121

118-
if (updated) {
119-
fs.writeFileSync(file, contents);
122+
if (updated) {
123+
fs.writeFileSync(file, contents);
124+
}
120125
}
121126
}
122127
}

packages/perspective-esbuild-plugin/worker.js

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -154,29 +154,6 @@ exports.WorkerPlugin = function WorkerPlugin(options = {}) {
154154
loader: "text",
155155
};
156156
});
157-
158-
build.onEnd(({ metafile }) => {
159-
for (const file of Object.keys(metafile.outputs)) {
160-
if (file.endsWith(".js")) {
161-
let contents = fs.readFileSync(file).toString();
162-
const symbol = contents.match(
163-
/__PSP_INLINE_WORKER__\(([a-zA-Z0-9_\$]+?)\)/
164-
);
165-
if (symbol?.[1]) {
166-
const filename = contents.match(
167-
new RegExp(`${symbol[1]}\\s*?=\\s*?\\"(.+?)\\"`)
168-
);
169-
170-
contents = contents.replace(
171-
/__PSP_INLINE_WORKER__\([a-zA-Z0-9_\$]+?\)/,
172-
`"${filename[1]}"`
173-
);
174-
175-
fs.writeFileSync(file, contents);
176-
}
177-
}
178-
}
179-
});
180157
}
181158

182159
return {

rust/perspective-python/perspective/tests/table/test_table_arrow.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,27 @@ def test_table_arrow_loads_int_stream(self, util):
117117
"d": data[3],
118118
}
119119

120+
def test_empty_arrow(self, util):
121+
table = pa.table(
122+
{
123+
"col1": [1, 2, 3],
124+
"col2": ["abc", "foo", "bar"],
125+
}
126+
)
127+
128+
empty_table = table.schema.empty_table()
129+
assert client.table(table, name="table").size() == 3
130+
assert client.table(empty_table, name="table_empty_bad").size() == 0
131+
assert client.table(table, name="table").schema() == {
132+
"col1": "integer",
133+
"col2": "string",
134+
}
135+
136+
assert client.table(empty_table, name="table").schema() == {
137+
"col1": "integer",
138+
"col2": "string",
139+
}
140+
120141
def test_table_arrow_loads_float_stream(self, util):
121142
data = [[i for i in range(10)], [i * 1.5 for i in range(10)]]
122143
arrow_data = util.make_arrow(["a", "b"], data)

rust/perspective-python/src/client/client_sync.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use super::python::*;
2626
use crate::py_err::ResultTClientErrorExt;
2727
use crate::server::PySyncServer;
2828

29-
#[pyclass]
29+
#[pyclass(module = "perspective")]
3030
#[derive(Clone)]
3131
pub struct ProxySession(perspective_client::ProxySession);
3232

@@ -81,7 +81,7 @@ trait PyFutureExt: Future {
8181
impl<F: Future> PyFutureExt for F {}
8282

8383
#[doc = crate::inherit_docs!("client.md")]
84-
#[pyclass(subclass)]
84+
#[pyclass(subclass, module = "perspective")]
8585
pub struct Client(pub(crate) PyClient);
8686

8787
#[pymethods]
@@ -147,7 +147,7 @@ impl Client {
147147
}
148148

149149
#[doc = crate::inherit_docs!("table.md")]
150-
#[pyclass(subclass, name = "Table")]
150+
#[pyclass(subclass, name = "Table", module = "perspective")]
151151
pub struct Table(PyTable);
152152

153153
assert_table_api!(Table);
@@ -272,7 +272,7 @@ impl Table {
272272
}
273273

274274
#[doc = crate::inherit_docs!("view.md")]
275-
#[pyclass(subclass, name = "View")]
275+
#[pyclass(subclass, name = "View", module = "perspective")]
276276
pub struct View(PyView);
277277

278278
assert_view_api!(View);

rust/perspective-python/src/server/server_sync.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ use pyo3::types::{PyAny, PyBytes};
2222

2323
use crate::client::python::PyClient;
2424

25-
#[pyclass]
25+
#[pyclass(module = "perspective")]
2626
#[derive(Clone)]
2727
pub struct PySyncSession {
2828
session: Arc<RwLock<Option<LocalSession>>>,
2929
}
3030

31-
#[pyclass(subclass)]
31+
#[pyclass(subclass, module = "perspective")]
3232
#[derive(Clone, Default)]
3333
pub struct PySyncServer {
3434
pub server: Server,

0 commit comments

Comments
 (0)