Skip to content

Commit

Permalink
Add the path of Matplotlib to the link search (for Anaconda)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris00 committed Mar 3, 2024
1 parent ffbd993 commit 37bd30e
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 6 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: '3.12'
if: ${{ ! startsWith(matrix.build, 'Anaconda') }}
- name: Install Matplotlib (pip)
if: ${{ ! startsWith(matrix.build, 'Anaconda') }}
run: pip install matplotlib
Expand All @@ -67,6 +68,7 @@ jobs:
run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }}
shell: bash
- run: rustup target add ${{ matrix.target }}
- run: cargo build --verbose
- run: cargo test tests --verbose
- run: cargo build -vv
- run: cargo test
if: ${{ ! startsWith(matrix.build, 'Anaconda') }}
- run: cargo run --example a_simple_example
57 changes: 57 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::{
env,
path::{Path, PathBuf},
process::Command,
};

fn conda_bin() -> String {
match env::var("CONDA") {
Ok(mut p) => {
p.push_str("/bin/conda");
p
}
Err(_) => "conda".to_string()
}
}

fn conda_path() -> Result<PathBuf, std::io::Error> {
Command::new(conda_bin()).args(["info", "--base"]).output()
.map(|o| {
let base = String::from_utf8_lossy(&o.stdout);
base.as_ref().trim().into()
})
}

fn main() {
let matplotlib = "import matplotlib; print(matplotlib.__file__)";

let plt = Command::new("python3").args(["-c", matplotlib]).output();
if let Ok(plt) = plt {
if plt.status.success() {
// The Python in the PATH has matplotlib.
return
}
}
// See whether Anaconda Python is installed and has matplotlib.
if let Ok(conda) = conda_path() {
let python = conda.join("bin").join("python3");
let plt = Command::new(python).args(["-c", matplotlib]).output();
if let Ok(plt) = plt {
if plt.status.success() {
let plt = String::from_utf8_lossy(&plt.stdout);
let plt = Path::new(plt.as_ref());
if let Some(d) = plt.parent().and_then(|d| d.parent()) {
let d = d.to_str().unwrap();
println!("cargo:rustc-env=PYTHONHOME={d}");
return
}
}
}
}
panic!("Python or package matplotlib not found (including in Anaconda)");

// if let Some(d) = plt_path.parent().and_then(|d| d.parent()) {
// let d = d.to_str().unwrap();
// println!("cargo:rustc-env=MATPLOTLIB_DIR={d}");
// }
}
84 changes: 80 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use std::{
fmt::{Display, Formatter},
path::Path, pin::Pin, borrow::Cow,
sync::Once,
};
use lazy_static::lazy_static;
use pyo3::{
Expand Down Expand Up @@ -88,7 +89,7 @@ impl Display for Error {
write!(f, "The matplotlib library has not been found.\n\
Please install it. See https://matplotlib.or/\n\
If you use Anaconda, see https://github.com/PyO3/pyo3/issues/1554"),
Error::FileNotFoundError =>
Error::FileNotFoundError =>
write!(f, "A path contains an element that is not a \
directory or does not exist"),
Error::PermissionError =>
Expand All @@ -102,11 +103,33 @@ If you use Anaconda, see https://github.com/PyO3/pyo3/issues/1554"),

impl std::error::Error for Error {}

fn initialize_python() {
static INIT: Once = Once::new();

INIT.call_once(|| {
if let Some(python_home) = option_env!("PYTHONHOME") {
// The Python C API uses null-terminated UTF-16 strings,
// so we need to encode the path into that format here.
let mut python_home: Vec<u16>
= python_home.encode_utf16().collect();
python_home.push(0);
unsafe {
pyo3::ffi::Py_SetPythonHome(python_home.as_ptr() as *const _);
}

// Manually initialize PyO3.
pyo3::prepare_freethreaded_python();
}
})
}

/// Import and return a handle to the module `$m`.
macro_rules! pyimport { ($m: literal) => {
macro_rules! pyimport { ($m: literal) => {{
initialize_python();
Python::with_gil(|py|
PyModule::import(py, intern!(py, $m)).map(|m| m.into()))
}}
PyModule::import(py, intern!(py, $m)).map(|m| m.into())
)
}}}

lazy_static! {
// Import matplotlib modules.
Expand Down Expand Up @@ -445,6 +468,29 @@ impl Axes {
}


pub fn contour<'a>(&'a mut self, ) -> Contour<'a> {
Contour {
axes: self,
options: PlotOptions::new(),
}
}

pub fn contour_fun<'a, F>(
&'a mut self,
f: F,
ab: [f64; 2],
cd: [f64; 2],
) -> ContourFun<'a, F>
where F: FnMut(f64, f64) -> f64 {
ContourFun {
axes: self,
options: PlotOptions::new(),
f, ab, cd,
n1: 100,
n2: 100,
}
}

#[must_use]
pub fn scatter<D>(&mut self, x: D, y: D) -> &mut Self
where D: AsRef<[f64]> {
Expand Down Expand Up @@ -801,6 +847,36 @@ where F: FnMut(f64) -> f64 {
}


#[must_use]
pub struct Contour<'a> {
axes: &'a Axes,
options: PlotOptions<'a>,
}

impl<'a> Contour<'a> {
set_plotoptions!();

}


#[must_use]
pub struct ContourFun<'a, F> {
axes: &'a Axes,
options: PlotOptions<'a>,
f: F,
ab: [f64; 2],
cd: [f64; 2],
n1: usize,
n2: usize,
}

impl<'a, F> ContourFun<'a, F>
where F: FnMut(f64, f64) -> f64 {
set_plotoptions!();

}


impl Line2D {
fn set_kw(&self, prop: &str, v: impl ToPyObject) {
Python::with_gil(|py| {
Expand Down

0 comments on commit 37bd30e

Please sign in to comment.