diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58403644..0a19afc1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,8 +43,11 @@ jobs: components: clippy targets: wasm32-unknown-unknown # lint plotly_static for all features - - run: cargo clippy -p plotly_static --features geckodriver,webdriver_download -- -D warnings -A deprecated - - run: cargo clippy -p plotly_static --features chromedriver,webdriver_download -- -D warnings -A deprecated + - run: | + export WEBDRIVER_PATH="${{ steps.setup-chrome.outputs.chromedriver-path }}" + export BROWSER_PATH="${{ steps.setup-chrome.outputs.chrome-path }}" + cargo clippy -p plotly_static --features geckodriver,webdriver_download -- -D warnings -A deprecated + cargo clippy -p plotly_static --features chromedriver,webdriver_download -- -D warnings -A deprecated # lint the main library workspace for non-wasm target - run: cargo clippy --features all -- -D warnings -A deprecated # lint the non-wasm examples @@ -132,7 +135,10 @@ jobs: # Run tests on Ubuntu with Chrome - name: Run tests (${{ matrix.os }} - Chrome) if: matrix.os == 'ubuntu-latest' && matrix.browser == 'chrome' - run: cargo test --workspace --features ${{ matrix.features }} --exclude plotly_kaleido + run: | + export WEBDRIVER_PATH="${{ steps.setup-chrome.outputs.chromedriver-path }}" + export BROWSER_PATH="${{ steps.setup-chrome.outputs.chrome-path }}" + cargo test --workspace --features ${{ matrix.features }} --exclude plotly_kaleido # Install xvfb for Firefox WebGL support - name: Install xvfb @@ -146,6 +152,7 @@ jobs: if: matrix.os == 'ubuntu-latest' && matrix.browser == 'firefox' run: | # Set environment variables for Firefox WebDriver + export WEBDRIVER_PATH="/usr/local/share/gecko_driver" export BROWSER_PATH="${{ steps.setup-firefox.outputs.firefox-path }}" export RUST_LOG="debug" export RUST_BACKTRACE="1" @@ -159,7 +166,10 @@ jobs: # Run tests on macOS with Chrome - name: Run tests (${{ matrix.os }} - Chrome) if: matrix.os == 'macos-latest' && matrix.browser == 'chrome' - run: cargo test --workspace --features ${{ matrix.features }} --exclude plotly_kaleido + run: | + export WEBDRIVER_PATH="${{ steps.setup-chrome.outputs.chromedriver-path }}" + export BROWSER_PATH="${{ steps.setup-chrome.outputs.chrome-path }}" + cargo test --workspace --features ${{ matrix.features }} --exclude plotly_kaleido # Run tests on Windows with Chrome WebDriver - name: Run tests (${{ matrix.os }} - Chrome) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ec42fd0..4cfff0b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a https://github.com/plotly/plotly.rs/pull/350 +## [Unreleased] + +### Fixed + +- [#5583](https://github.com/plotly/plotly.rs/issues/5583) Use string axis ids for trace `x_axis` and `y_axis` setters + ## [0.14.1] - 2026-02-15 ### Fixed diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index 28e3bd2b..1b4e874c 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -893,6 +893,12 @@ pub enum Reference { Paper, } +/// Axis id for a 2D cartesian x axis. +pub type XAxisId = String; + +/// Axis id for a 2D cartesian y axis. +pub type YAxisId = String; + #[derive(Serialize, Clone, Debug)] pub struct Pad { t: usize, @@ -1799,6 +1805,14 @@ mod tests { assert_eq!(to_value(Reference::Paper).unwrap(), json!("paper")); } + #[test] + fn serialize_axis_id() { + assert_eq!(to_value(XAxisId::from("x")).unwrap(), json!("x")); + assert_eq!(to_value(XAxisId::from("x3")).unwrap(), json!("x3")); + assert_eq!(to_value(YAxisId::from("y")).unwrap(), json!("y")); + assert_eq!(to_value(YAxisId::from("y8")).unwrap(), json!("y8")); + } + #[test] #[rustfmt::skip] fn serialize_legend_group_title() { diff --git a/plotly/src/traces/contour.rs b/plotly/src/traces/contour.rs index 359eaf37..633b36ca 100644 --- a/plotly/src/traces/contour.rs +++ b/plotly/src/traces/contour.rs @@ -403,8 +403,8 @@ where Box::new(self) } - pub fn x_axis(mut self, axis: &str) -> Box { - self.x_axis = Some(axis.to_string()); + pub fn x_axis(mut self, axis: impl Into) -> Box { + self.x_axis = Some(axis.into()); Box::new(self) } @@ -418,8 +418,8 @@ where Box::new(self) } - pub fn y_axis(mut self, axis: &str) -> Box { - self.y_axis = Some(axis.to_string()); + pub fn y_axis(mut self, axis: impl Into) -> Box { + self.y_axis = Some(axis.into()); Box::new(self) } diff --git a/plotly/src/traces/scatter.rs b/plotly/src/traces/scatter.rs index e96784c3..0e020896 100644 --- a/plotly/src/traces/scatter.rs +++ b/plotly/src/traces/scatter.rs @@ -528,4 +528,21 @@ mod tests { assert_eq!(to_value(trace).unwrap(), expected); } + + #[test] + fn serialize_scatter_axis_ids() { + let trace = Scatter::new(vec![0, 1], vec![2, 3]) + .x_axis("x2") + .y_axis("y3"); + + let expected = json!({ + "type": "scatter", + "x": [0, 1], + "y": [2, 3], + "xaxis": "x2", + "yaxis": "y3" + }); + + assert_eq!(to_value(trace).unwrap(), expected); + } } diff --git a/plotly_derive/src/field_setter.rs b/plotly_derive/src/field_setter.rs index 7f6b6b2b..f54c88cb 100644 --- a/plotly_derive/src/field_setter.rs +++ b/plotly_derive/src/field_setter.rs @@ -336,12 +336,28 @@ impl FieldReceiver { crate::color::ColorArray(value).into() )], ), - FieldType::OptionString => ( - quote![impl AsRef], - quote![value.as_ref().to_owned()], - quote![], - ), - FieldType::OptionOther(inner_ty) => (quote![#inner_ty], quote![value], quote![]), + FieldType::OptionString => { + if matches!(kind, Kind::Trace) + && matches!(field_ident.to_string().as_str(), "x_axis" | "y_axis") + { + (quote![impl Into], quote![value.into()], quote![]) + } else { + ( + quote![impl AsRef], + quote![value.as_ref().to_owned()], + quote![], + ) + } + } + FieldType::OptionOther(inner_ty) => { + if matches!(kind, Kind::Trace) + && matches!(field_ident.to_string().as_str(), "x_axis" | "y_axis") + { + (quote![impl Into<#inner_ty>], quote![value.into()], quote![]) + } else { + (quote![#inner_ty], quote![value], quote![]) + } + } FieldType::OptionVecString => ( quote![Vec>], quote![value.into_iter().map(|v| v.as_ref().to_owned()).collect()], diff --git a/plotly_static/build.rs b/plotly_static/build.rs index f8b2c076..aeaa4828 100644 --- a/plotly_static/build.rs +++ b/plotly_static/build.rs @@ -174,19 +174,19 @@ fn setup_driver(config: &WebdriverDownloadConfig) -> Result<()> { match config.driver_name { CHROMEDRIVER_NAME => { let driver_info = ChromedriverInfo::new(webdriver_bin.clone(), browser_path); - runtime - .block_on(async { download_with_retry(&driver_info, false, true, 1).await }) - .with_context(|| { - format!("Failed to download and install {}", config.driver_name) - })?; + let dl_res = runtime + .block_on(async { download_with_retry(&driver_info, false, true, 1).await }); + if let Err(e) = dl_res { + return Err(anyhow!("Failed to download and install chromedriver").context(e)); + } } GECKODRIVER_NAME => { let driver_info = GeckodriverInfo::new(webdriver_bin.clone(), browser_path); - runtime - .block_on(async { download_with_retry(&driver_info, false, true, 1).await }) - .with_context(|| { - format!("Failed to download and install {}", config.driver_name) - })?; + let dl_res = runtime + .block_on(async { download_with_retry(&driver_info, false, true, 1).await }); + if let Err(e) = dl_res { + return Err(anyhow!("Failed to download and install geckodriver").context(e)); + } } _ => return Err(anyhow!("Unsupported driver type: {}", config.driver_name)), }