Skip to content
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
129 changes: 124 additions & 5 deletions guide/src/project_layout.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,130 @@
# Project Layout

mention how to package type stubs
Maturin expects a particular project layout depending on the contents of the
package.

## Pure Rust Project
## Pure Rust project

TODO
For a pure Rust project, the structure is as expected and what you get from `cargo new`:

## Mixed Rust/Python Project
```
my-rust-project/
├── Cargo.toml
├── pyproject.toml # required for maturing configuration
└── src
├── lib.rs # default for library crates
└── main.rs # default for binary crates
```

TODO
maturin will add a necessary `__init__.py` to the package when building the
wheel. For convenience, this file includes the following:

```python
from .my_project import *

__doc__ = .my_project.__doc__
```

such that the module functions may be called directly with:

```python
import my_project
my_project.foo()
```

rather than:

```python
from my_project import my_project
```

N.B.: there is currently no way to tell maturin to include extra data (e.g.
type stubs or `package_data` in setuptools) for a pure Rust project. Instead,
consider using the layout described below for the mixed Rust/Python project.

## Mixed Rust/Python project

To create a mixed Rust/Python project, add a directory with your package name
(i.e. matching `lib.name` in your `Cargo.toml`) to contain the Python source:

```
my-rust-and-python-project
├── Cargo.toml
├── my_project # <<< add this directory and put Python code in here
│ ├── __init__.py
│ └── bar.py
├── pyproject.toml
├── Readme.md
└── src
└── lib.rs
```

Note that in a mixed Rust/Python project, maturin _does not_ modify the
existing `__init__.py` in the root package, so now to import the rust module in
Python you must use:

```python
from my_project import my_project
```

You can modify `__init__.py` yourself (see above) if you would like to import
functions Rust functions from a higher-level namespace.

### Alternate Python source directory (src layout)

Having a directory with `package_name` in the root of the project can
occasionally cause confusion as Python allows importing local packages and
modules. A popular way to avoid this is with the `src`-layout, where the Python
package is nested within a `src` directory. Unfortunately this interferes with
the structure of a typical Rust project. Fortunately, Python is nor particular
about the name of the parent source directory. You tell maturin to use a
different Python source directory in `Cargo.toml` by setting
`package.metadata.maturin.python-source`. For example:

```toml
[package.metadata.maturin]
python-source = "python"
```

then the project structure would look like this:

```
my-rust-and-python-project
├── Cargo.toml
├── python
│ └── my_project
│ ├── __init__.py
│ └── bar.py
├── pyproject.toml
├── README.md
└── src
└── lib.rs
```

### Adding type information

The simplest way to add type information for distribution is to use the mixed
Rust/Python projcet layout. In this layout, additional files in the Python
source dir (but not in `.gitignore`) will be automatically included in the
build outputs (source distribution and/or wheel).

To distribute typing information, you need to add:

* an empty marker file called `py.typed` in the root of the Python package
* inline types in Python files and/or `.pyi` "stub" files

```
my-project
├── Cargo.toml
├── python
│ └── my_project
│ ├── __init__.py
│ ├── py.typed # <<< add this empty file
│ ├── my_project.pyi # <<< add type stubs for Rust functions in the my_project module here
│ ├── bar.pyi # <<< add type stubs for bar.py here OR type bar.py inline
│ └── bar.py
├── pyproject.toml
├── README.md
└── src
└── lib.rs
```
Loading