Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Vega-Lite 5.19, Vega 5.30, and update rust dependencies #171

Merged
merged 9 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,178 changes: 503 additions & 675 deletions Cargo.lock

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,45 @@ strip = true # Automatically strip symbols from the binary
opt-level = "z" # Optimize for size
lto = true
codegen-units = 1

[workspace.dependencies]
anyhow = "1.0"
assert_cmd = "2.0"
clap = { version = "4.5", features = ["derive"] }

# Deno crates that correspond to 1.44.4
deno_core = "0.290.0"
deno_emit = "0.42.0"
deno_graph = "0.78.1"
deno_runtime = "0.166.0"

dircpy = "0.3"
dssim = "3.2.4"
env_logger = "0.10.0"
fontdb = { version = "0.18.0", features = ["fontconfig"] }
futures = "0.3.30"
futures-util = "0.3.30"
image = { version = "0.24.7", default-features = false, features = ["jpeg"] }
itertools = "0.11.0"
lazy_static = "1.4.0"
log = "0.4.20"
lz-str = "0.2.1"
png = "0.17.10"
predicates = "3.0.2"
pyo3 = { version = "0.21", features = ["extension-module", "anyhow", "abi3-py37"] }
pythonize = "0.21"
regex = "1"
reqwest = { version = "0.11.20", default-features = false, features = ["rustls-tls"] }
resvg = "0.42.0"
rstest = "0.18.2"
semver = "1.0.20"
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.106"
shellexpand = "3.1.0"
svg2pdf = "0.11.0"
tempfile = "3.8.0"
tiny-skia = "0.11.4"
tokio = { version = "1.37", features = ["macros", "rt-multi-thread"] }
ttf-parser = "0.21.1"
usvg = "0.42.0"
zip-extract = "0.1"
4,322 changes: 1,328 additions & 2,994 deletions thirdparty_rust.yaml

Large diffs are not rendered by default.

14 changes: 6 additions & 8 deletions vl-convert-python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ publish = false
[package.metadata.release]
release = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "vl_convert"
crate-type = ["cdylib"]

[dependencies]
vl-convert-rs = { path = "../vl-convert-rs", version= "1.2.3" }
pyo3 = { version = "0.20.0", features = ["extension-module", "anyhow", "abi3-py37"] }
lazy_static = "1.4.0"
futures = "0.3.28"
pythonize = "0.20.0"
tokio = { version= "1.32" }

vl-convert-rs = { path = "../vl-convert-rs", version = "1.2.3" }
pyo3 = { workspace = true }
lazy_static = { workspace = true }
futures = { workspace = true }
pythonize = { workspace = true }
tokio = { workspace = true }
52 changes: 27 additions & 25 deletions vl-convert-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyDict};
use pythonize::{depythonize, pythonize};
use pythonize::{depythonize_bound as depythonize, pythonize};
use std::borrow::Cow;
use std::str::FromStr;
use std::sync::Mutex;
use vl_convert_rs::converter::{FormatLocale, Renderer, TimeFormatLocale, VgOpts, VlOpts};
Expand Down Expand Up @@ -366,7 +367,7 @@ fn vega_to_png(
};

Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, png_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, png_data.as_slice()))
}))
}

Expand Down Expand Up @@ -442,7 +443,7 @@ fn vegalite_to_png(
};

Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, png_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, png_data.as_slice()))
}))
}

Expand Down Expand Up @@ -498,7 +499,7 @@ fn vega_to_jpeg(
};

Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, jpeg_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, jpeg_data.as_slice()))
}))
}

Expand Down Expand Up @@ -574,7 +575,7 @@ fn vegalite_to_jpeg(
};

Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, jpeg_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, jpeg_data.as_slice()))
}))
}

Expand Down Expand Up @@ -624,7 +625,7 @@ fn vega_to_pdf(
}
};
Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, pdf_bytes.as_slice()))
PyObject::from(PyBytes::new_bound(py, pdf_bytes.as_slice()))
}))
}

Expand Down Expand Up @@ -695,7 +696,7 @@ fn vegalite_to_pdf(
};

Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, pdf_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, pdf_data.as_slice()))
}))
}

Expand Down Expand Up @@ -847,7 +848,7 @@ fn vega_to_html(
fn svg_to_png(svg: &str, scale: Option<f32>, ppi: Option<f32>) -> PyResult<PyObject> {
let png_data = vl_convert_rs::converter::svg_to_png(svg, scale.unwrap_or(1.0), ppi)?;
Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, png_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, png_data.as_slice()))
}))
}

Expand All @@ -864,7 +865,7 @@ fn svg_to_png(svg: &str, scale: Option<f32>, ppi: Option<f32>) -> PyResult<PyObj
fn svg_to_jpeg(svg: &str, scale: Option<f32>, quality: Option<u8>) -> PyResult<PyObject> {
let jpeg_data = vl_convert_rs::converter::svg_to_jpeg(svg, scale.unwrap_or(1.0), quality)?;
Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, jpeg_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, jpeg_data.as_slice()))
}))
}

Expand All @@ -881,23 +882,23 @@ fn svg_to_pdf(svg: &str, scale: Option<f32>) -> PyResult<PyObject> {
warn_if_scale_not_one_for_pdf(scale)?;
let pdf_data = vl_convert_rs::converter::svg_to_pdf(svg)?; // Always pass 1.0 as scale
Ok(Python::with_gil(|py| -> PyObject {
PyObject::from(PyBytes::new(py, pdf_data.as_slice()))
PyObject::from(PyBytes::new_bound(py, pdf_data.as_slice()))
}))
}

/// Helper function to parse an input Python string or dict as a serde_json::Value
fn parse_json_spec(vl_spec: PyObject) -> PyResult<serde_json::Value> {
Python::with_gil(|py| -> PyResult<serde_json::Value> {
if let Ok(vl_spec) = vl_spec.extract::<&str>(py) {
match serde_json::from_str::<serde_json::Value>(vl_spec) {
if let Ok(vl_spec) = vl_spec.extract::<Cow<str>>(py) {
match serde_json::from_str::<serde_json::Value>(vl_spec.as_ref()) {
Ok(vl_spec) => Ok(vl_spec),
Err(err) => Err(PyValueError::new_err(format!(
"Failed to parse vl_spec string as JSON: {}",
err
))),
}
} else if let Ok(vl_spec) = vl_spec.downcast::<PyDict>(py) {
match depythonize(vl_spec) {
} else if let Ok(vl_spec) = vl_spec.downcast_bound::<PyDict>(py) {
match depythonize(vl_spec.as_any().clone()) {
Ok(vl_spec) => Ok(vl_spec),
Err(err) => Err(PyValueError::new_err(format!(
"Failed to parse vl_spec dict as JSON: {}",
Expand All @@ -913,17 +914,17 @@ fn parse_json_spec(vl_spec: PyObject) -> PyResult<serde_json::Value> {
/// Helper function to parse an input Python string or dict as a FormatLocale
fn parse_format_locale(v: PyObject) -> PyResult<FormatLocale> {
Python::with_gil(|py| -> PyResult<FormatLocale> {
if let Ok(name) = v.extract::<&str>(py) {
let format_locale = FormatLocale::Name(name.to_string());
if let Ok(name) = v.extract::<Cow<str>>(py) {
let format_locale = FormatLocale::Name(name.as_ref().to_string());
if format_locale.as_object().is_err() {
Err(PyValueError::new_err(
format!("Invalid format_locale name: {name}\nSee https://github.com/d3/d3-format/tree/main/locale for available names")
))
} else {
Ok(format_locale)
}
} else if let Ok(obj) = v.downcast::<PyDict>(py) {
match depythonize(obj) {
} else if let Ok(obj) = v.downcast_bound::<PyDict>(py) {
match depythonize(obj.as_any().clone()) {
Ok(obj) => Ok(FormatLocale::Object(obj)),
Err(err) => Err(PyValueError::new_err(format!(
"Failed to parse format_locale dict as JSON: {}",
Expand All @@ -947,17 +948,17 @@ fn parse_option_format_locale(v: Option<PyObject>) -> PyResult<Option<FormatLoca
/// Helper function to parse an input Python string or dict as a TimeFormatLocale
fn parse_time_format_locale(v: PyObject) -> PyResult<TimeFormatLocale> {
Python::with_gil(|py| -> PyResult<TimeFormatLocale> {
if let Ok(name) = v.extract::<&str>(py) {
let time_format_locale = TimeFormatLocale::Name(name.to_string());
if let Ok(name) = v.extract::<Cow<str>>(py) {
let time_format_locale = TimeFormatLocale::Name(name.as_ref().to_string());
if time_format_locale.as_object().is_err() {
Err(PyValueError::new_err(
format!("Invalid time_format_locale name: {name}\nSee https://github.com/d3/d3-time-format/tree/main/locale for available names")
))
} else {
Ok(time_format_locale)
}
} else if let Ok(obj) = v.downcast::<PyDict>(py) {
match depythonize(obj) {
} else if let Ok(obj) = v.downcast_bound::<PyDict>(py) {
match depythonize(obj.as_any().clone()) {
Ok(obj) => Ok(TimeFormatLocale::Object(obj)),
Err(err) => Err(PyValueError::new_err(format!(
"Failed to parse time_format_locale dict as JSON: {}",
Expand Down Expand Up @@ -1138,7 +1139,7 @@ fn javascript_bundle(snippet: Option<String>, vl_version: Option<&str>) -> PyRes

/// Convert Vega-Lite specifications to other formats
#[pymodule]
fn vl_convert(_py: Python, m: &PyModule) -> PyResult<()> {
fn vl_convert(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(vegalite_to_vega, m)?)?;
m.add_function(wrap_pyfunction!(vegalite_to_svg, m)?)?;
m.add_function(wrap_pyfunction!(vegalite_to_scenegraph, m)?)?;
Expand Down Expand Up @@ -1173,8 +1174,9 @@ fn warn_if_scale_not_one_for_pdf(scale: Option<f32>) -> PyResult<()> {
if scale != 1.0 {
Python::with_gil(|py| -> PyResult<()> {
let warning_message = "The scale argument is no longer supported for PDF export.";
let deprecation_warning = py.get_type::<pyo3::exceptions::PyDeprecationWarning>();
PyErr::warn(py, deprecation_warning, warning_message, 1)?;
let deprecation_warning =
py.get_type_bound::<pyo3::exceptions::PyDeprecationWarning>();
PyErr::warn_bound(py, &deprecation_warning, warning_message, 1)?;
Ok(())
})?;
}
Expand Down
16 changes: 3 additions & 13 deletions vl-convert-python/tests/test_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,7 @@ def load_expected_png(name, vl_version, theme=None):
@pytest.mark.parametrize("name", ["circle_binned", "seattle-weather", "stacked_bar_h"])
@pytest.mark.parametrize(
"vl_version",
[
"v5_8",
"v5_11",
"v5_12",
"v5_13",
"v5_14",
"v5_15",
"v5_16",
"v5_17",
"v5_18",
],
["v5_8", "v5_12", "v5_13", "v5_14", "v5_15", "v5_16", "v5_17", "v5_18", "v5_19"],
)
@pytest.mark.parametrize("as_dict", [False, True])
def test_vega(name, vl_version, as_dict):
Expand All @@ -106,14 +96,14 @@ def test_vega(name, vl_version, as_dict):
"vl_version",
[
"5.8",
"5.11",
"5.12",
"5.13",
"5.14",
"5.15",
"5.16",
"5.17",
"5.18",
"5.19",
],
)
def test_vegalite_to_html_no_bundle(name, vl_version):
Expand Down Expand Up @@ -142,14 +132,14 @@ def test_vegalite_to_html_no_bundle(name, vl_version):
"vl_version",
[
"5.8",
"5.11",
"5.12",
"5.13",
"5.14",
"5.15",
"5.16",
"5.17",
"5.18",
"5.19",
],
)
def test_vegalite_to_html_bundle(name, vl_version):
Expand Down
Loading
Loading