Как построить иерархию модулей с pyo3? - PullRequest
0 голосов
/ 09 января 2020

Попытка построить иерархию модулей с pyo3 и этим кодом

pub mod types;
pub mod sources;

use pyo3::prelude::*;
use pyo3::wrap_pymodule;

use sources::file::{find_days, read_many, read_one};


#[pymodule]
fn file(_py: Python, m: &PyModule) -> PyResult<()> {

    #[pyfn(m, "find_days")]
    fn find_days_py(_py: Python, dir: String) -> PyResult<Vec<String>> {
        let out = find_days(&dir)?;
        Ok(out.iter().map(|x| String::from(x.to_str().unwrap())).collect())
    }

    Ok(())
}

#[pymodule]
fn sources(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pymodule!(file))?;
    Ok(())
}

#[pymodule]
fn cstuff(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pymodule!(sources))?;
    // m.add("__path__", vec![""])?;
    Ok(())
}

Код собирается и работает нормально, за исключением того, что когда я пытаюсь импортировать его, я получаю эту ошибку

In [1]: import cstuff.sources.file                                                                      
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-97430c5317d9> in <module>
----> 1 import cstuff.sources.file

ModuleNotFoundError: No module named 'cstuff.sources'; 'cstuff' is not a package

Из того, что я понимаю из документации python, модуль - это пакет, если он имеет атрибут __path__.

Я могу добавить это с помощью m.add("__path__", vec![""])?;, после этого import работает как положено, но только когда python запускается из каталога с файлом .so, что ожидается.

Проблема в том, что я не знаю __path__ заранее. Как это исправить, есть ли способ заставить python установить __path__?

...