diff --git a/Changelog.md b/Changelog.md index 09300833e..9ead22a5b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +* Add basic support for implicit namespaces [#1645](https://github.com/PyO3/maturin/pull/1696) + ## [1.1.0] - 2023-06-10 * Add basic support for GraalPy in [#1645](https://github.com/PyO3/maturin/pull/1645) @@ -152,7 +154,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * **Breaking Change**: Remove support for specifying python package metadata in `Cargo.toml` in [#1200](https://github.com/PyO3/maturin/pull/1200). Python package metadata should be specified in the `project` section of `pyproject.toml` instead as [PEP 621](https://peps.python.org/pep-0621/) specifies. -* Initial support for shipping bin targets as wasm32-wasi binaries that are run through wasmtime in [#1107](https://github.com/PyO3/maturin/pull/1107). +* Initial support for shipping bin targets as wasm32-wasi binaries that are run through wasmtime in [#1107](https://github.com/PyO3/maturin/pull/1107). Note that wasmtime currently only support the five most popular platforms and that wasi binaries have restrictions when interacting with the host. Usage is by setting `--target wasm32-wasi`. * Add support for python first [`src` project layout](https://py-pkgs.org/04-package-structure.html#the-source-layout) in [#1185](https://github.com/PyO3/maturin/pull/1185) diff --git a/src/project_layout.rs b/src/project_layout.rs index 5bcd6312f..1469cbd7f 100644 --- a/src/project_layout.rs +++ b/src/project_layout.rs @@ -387,12 +387,6 @@ impl ProjectLayout { }; if python_module.is_dir() { - if !python_module.join("__init__.py").is_file() - && !python_module.join("__init__.pyi").is_file() - { - bail!("Found a directory with the module name ({}) next to Cargo.toml, which indicates a mixed python/rust project, but the directory didn't contain an __init__.py file.", module_name) - } - eprintln!("🍹 Building a mixed python/rust project"); Ok(ProjectLayout { diff --git a/test-crates/pyo3-mixed-implicit/Cargo.toml b/test-crates/pyo3-mixed-implicit/Cargo.toml new file mode 100644 index 000000000..fb22b7487 --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["Kevin Patterson "] +name = "pyo3-mixed-implicit" +version = "2.1.3" +description = "Implements a dummy function combining rust and python" +readme = "README.md" +edition = "2021" + +[dependencies] +pyo3 = { version = "0.19.0", features = ["extension-module"] } + +[lib] +name = "pyo3_mixed_implicit" +crate-type = ["cdylib"] diff --git a/test-crates/pyo3-mixed-implicit/README.md b/test-crates/pyo3-mixed-implicit/README.md new file mode 100644 index 000000000..3eec24982 --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/README.md @@ -0,0 +1,30 @@ +# pyo3-mixed-implicit + +A package for testing maturin with a mixed pyo3/python project with an implicit namespace package and Rust submodule. + +## Usage + +```bash +pip install . +``` + +```python +import pyo3_mixed_implicit +assert pyo3_mixed_implicit.some_rust.get_22() == 22 +``` + +## Testing + +Install tox: + +```bash +pip install tox +``` + +Run it: + +```bash +tox +``` + +The tests are in `tests/test_pyo3_mixed_implicit.py`, while the configuration is in tox.ini diff --git a/test-crates/pyo3-mixed-implicit/check_installed/check_installed.py b/test-crates/pyo3-mixed-implicit/check_installed/check_installed.py new file mode 100644 index 000000000..a3b2ddcaf --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/check_installed/check_installed.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import pyo3_mixed_implicit.some_rust as some_rust + +assert some_rust.get_22() == 22 +assert some_rust.double(lambda: 4) == 8 + +print("SUCCESS") diff --git a/test-crates/pyo3-mixed-implicit/pyproject.toml b/test-crates/pyo3-mixed-implicit/pyproject.toml new file mode 100644 index 000000000..f452a6edc --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["maturin>=0.15,<0.16"] +build-backend = "maturin" + +[project] +name = "pyo3_mixed_implicit.some_rust" +classifiers = [ + "Programming Language :: Python", + "Programming Language :: Rust" +] + +[tool.maturin] +features = ["pyo3/extension-module"] +module-name = "pyo3_mixed_implicit.some_rust.rust" +python-source = "pysrc" + diff --git a/test-crates/pyo3-mixed-implicit/pysrc/pyo3_mixed_implicit/some_rust/__init__.py b/test-crates/pyo3-mixed-implicit/pysrc/pyo3_mixed_implicit/some_rust/__init__.py new file mode 100644 index 000000000..21b0c5d6c --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/pysrc/pyo3_mixed_implicit/some_rust/__init__.py @@ -0,0 +1,4 @@ +from .rust import get_22 +from .double import double + +__all__ = ["get_22", "double"] diff --git a/test-crates/pyo3-mixed-implicit/pysrc/pyo3_mixed_implicit/some_rust/double.py b/test-crates/pyo3-mixed-implicit/pysrc/pyo3_mixed_implicit/some_rust/double.py new file mode 100644 index 000000000..2eed18d52 --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/pysrc/pyo3_mixed_implicit/some_rust/double.py @@ -0,0 +1,5 @@ +from typing import Callable + + +def double(fn: Callable[[], int]) -> int: + return 2 * fn() diff --git a/test-crates/pyo3-mixed-implicit/src/lib.rs b/test-crates/pyo3-mixed-implicit/src/lib.rs new file mode 100644 index 000000000..0c5711a3b --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/src/lib.rs @@ -0,0 +1,13 @@ +use pyo3::prelude::*; + +#[pyfunction] +fn get_22() -> usize { + 22 +} + +#[pymodule] +fn rust(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_wrapped(wrap_pyfunction!(get_22))?; + + Ok(()) +} diff --git a/test-crates/pyo3-mixed-implicit/tests/test_pyo3_mixed_implicit.py b/test-crates/pyo3-mixed-implicit/tests/test_pyo3_mixed_implicit.py new file mode 100644 index 000000000..1be6c8549 --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/tests/test_pyo3_mixed_implicit.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import pyo3_mixed_implicit.some_rust as some_rust + + +def test_get_rust_and_python(): + assert some_rust.get_22() == 22 + assert some_rust.double(lambda: 4) == 8 + + +print("SUCCESS") diff --git a/test-crates/pyo3-mixed-implicit/tox.ini b/test-crates/pyo3-mixed-implicit/tox.ini new file mode 100644 index 000000000..421774193 --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/tox.ini @@ -0,0 +1,7 @@ +[tox] +envlist = py36,py37,py38 +isolated_build = True + +[testenv] +deps = pytest +commands = pytest tests/ diff --git a/test-dockerfile.sh b/test-dockerfile.sh index b0d79780d..d6613be41 100755 --- a/test-dockerfile.sh +++ b/test-dockerfile.sh @@ -11,7 +11,7 @@ venv-docker/bin/pip install -U pip cffi # FIXME: Can we run the tests without activate? Currently hello-world fails because then the binary is not in PATH source venv-docker/bin/activate -for test_crate in hello-world cffi-pure cffi-mixed pyo3-pure pyo3-mixed pyo3-mixed-submodule +for test_crate in hello-world cffi-pure cffi-mixed pyo3-pure pyo3-mixed pyo3-mixed-submodule pyo3-mixed-implicit do echo "Testing $test_crate" docker run -e RUST_BACKTRACE=1 --rm -v "$(pwd):/io" -w /io/test-crates/$test_crate maturin build -i python3.11 diff --git a/tests/run.rs b/tests/run.rs index 06790c0c0..c0c105a89 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -67,6 +67,16 @@ fn develop_pyo3_mixed_submodule() { )); } +#[test] +fn develop_pyo3_mixed_implicit() { + handle_result(develop::test_develop( + "test-crates/pyo3-mixed-implicit", + None, + "develop-pyo3-mixed-implicit", + false, + )); +} + #[test] fn develop_pyo3_mixed_py_subdir() { handle_result(develop::test_develop( @@ -216,6 +226,17 @@ fn integration_pyo3_mixed_submodule() { )); } +#[test] +fn integration_pyo3_mixed_implicit() { + handle_result(integration::test_integration( + "test-crates/pyo3-mixed-implicit", + None, + "integration-pyo3-mixed-implicit", + false, + None, + )); +} + #[test] fn integration_pyo3_mixed_py_subdir() { handle_result(integration::test_integration(