Skip to content

Unnecessary restrictions on project layout due to bad heuristic #3204

Description

@h3har

Maturin seems to make incorrect assumptions about the project layout that restricts the kinds of wheels you can build with it. For example, when building mixed Rust/Python projects with python-source and module-name set, maturin assumes that the path pointed to by module-name is an existing Python module if: it either contains an __init__.py file or does not contain a Cargo.toml file.

This comes from the following excerpt in Maturin's source code:

let python_module = if !python_module.join("__init__.py").is_file()
    && python_module.join("Cargo.toml").is_file()
{
    debug!("No __init__.py file found in {}", python_module.display());
    None
} else {
    Some(python_module)
};

This prevents you having multiple top-level modules, e.g.:

module/
    python_code.py
_module.cp312-win_amd64.pyd

compiled from:

rust/
    lib.rs
src/
    module/
        python_code.py
Cargo.toml
pyproject.toml

This layout cannot be achieved by setting:

[tool.maturin]
python-source = "src"
module-name = "_module"

since maturin looks for src/_module, sees that src/_module/Cargo.toml doesn't exist, and determines that it must therefore be a Python module, yielding the following error when running maturin develop:

💥 maturin failed
  Caused by: python-source is set to `...\python\src`, but the python module at
`...\python\src\_module` does not exist. Either create the Python module or remove the `python-source` setting from
pyproject.toml.

Fundamentally: Maturin's code seems to assume that a mixed Rust/Python project consists of one Python module that contains the Rust extension module. However, this assumption is not correct: Python distributions can contain arbitrarily many top-level modules and there's no reason to require that the Rust extension module is inside the main Python module.

Feature Request

Maturin should not make unnecessary assumptions about project layout. Python distributions can contain arbitrarily many top-level modules - some may be plain Python code, some may be compiled extension modules, and others may be directories that contain both. Maturin's goal should basically be to copy the Python source tree into the wheel (subject to filtering), and insert the compiled extension module at the desired place implied by module-name, which may be at the root of the distribution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions