Git Product home page Git Product logo

pyo3 / maturin Goto Github PK

View Code? Open in Web Editor NEW
3.3K 26.0 222.0 6.71 MB

Build and publish crates with pyo3, cffi and uniffi bindings as well as rust binaries as python packages

Home Page: https://maturin.rs

License: Apache License 2.0

Rust 93.13% Python 4.82% Dockerfile 0.35% Shell 0.78% Jinja 0.45% JavaScript 0.44% CSS 0.03%
pyo3 python wheels cpython packaging pypi cffi pypy uniffi cross-compile

maturin's Introduction

PyO3

actions status benchmark codecov crates.io minimum rustc 1.63 discord server contributing notes

Rust bindings for Python, including tools for creating native Python extension modules. Running and interacting with Python code from a Rust binary is also supported.

Usage

PyO3 supports the following software versions:

  • Python 3.7 and up (CPython, PyPy, and GraalPy)
  • Rust 1.63 and up

You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.

Using Rust from Python

PyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use maturin. maturin is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps install maturin, use it to generate and build a new Python package, and then launch Python to import and execute a function from the package.

First, follow the commands below to create a new directory containing a new Python virtualenv, and install maturin into the virtualenv using Python's package manager, pip:

# (replace string_sum with the desired package name)
$ mkdir string_sum
$ cd string_sum
$ python -m venv .env
$ source .env/bin/activate
$ pip install maturin

Still inside this string_sum directory, now run maturin init. This will generate the new package source. When given the choice of bindings to use, select pyo3 bindings:

$ maturin init
โœ” ๐Ÿคท What kind of bindings to use? ยท pyo3
  โœจ Done! New project created string_sum

The most important files generated by this command are Cargo.toml and lib.rs, which will look roughly like the following:

Cargo.toml

[package]
name = "string_sum"
version = "0.1.0"
edition = "2021"

[lib]
# The name of the native library. This is the name which will be used in Python to import the
# library (i.e. `import string_sum`). If you change this, you must also change the name of the
# `#[pymodule]` in `src/lib.rs`.
name = "string_sum"
# "cdylib" is necessary to produce a shared library for Python to import from.
#
# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able
# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.:
# crate-type = ["cdylib", "rlib"]
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.21.2", features = ["extension-module"] }

src/lib.rs

use pyo3::prelude::*;

/// Formats the sum of two numbers as string.
#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
    Ok((a + b).to_string())
}

/// A Python module implemented in Rust. The name of this function must match
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
#[pymodule]
fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
    Ok(())
}

Finally, run maturin develop. This will build the package and install it into the Python virtualenv previously created and activated. The package is then ready to be used from python:

$ maturin develop
# lots of progress output as maturin runs the compilation...
$ python
>>> import string_sum
>>> string_sum.sum_as_string(5, 20)
'25'

To make changes to the package, just edit the Rust source code and then re-run maturin develop to recompile.

To run this all as a single copy-and-paste, use the bash script below (replace string_sum in the first command with the desired package name):

mkdir string_sum && cd "$_"
python -m venv .env
source .env/bin/activate
pip install maturin
maturin init --bindings pyo3
maturin develop

If you want to be able to run cargo test or use this project in a Cargo workspace and are running into linker issues, there are some workarounds in the FAQ.

As well as with maturin, it is possible to build using setuptools-rust or manually. Both offer more flexibility than maturin but require more configuration to get started.

Using Python from Rust

To embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter.

To install the Python shared library on Ubuntu:

sudo apt install python3-dev

To install the Python shared library on RPM based distributions (e.g. Fedora, Red Hat, SuSE), install the python3-devel package.

Start a new project with cargo new and add pyo3 to the Cargo.toml like this:

[dependencies.pyo3]
version = "0.21.2"
features = ["auto-initialize"]

Example program displaying the value of sys.version and the current user name:

use pyo3::prelude::*;
use pyo3::types::IntoPyDict;

fn main() -> PyResult<()> {
    Python::with_gil(|py| {
        let sys = py.import_bound("sys")?;
        let version: String = sys.getattr("version")?.extract()?;

        let locals = [("os", py.import_bound("os")?)].into_py_dict_bound(py);
        let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'";
        let user: String = py.eval_bound(code, None, Some(&locals))?.extract()?;

        println!("Hello {}, I'm Python {}", user, version);
        Ok(())
    })
}

The guide has a section with lots of examples about this topic.

Tools and libraries

  • maturin Build and publish crates with pyo3, rust-cpython or cffi bindings as well as rust binaries as python packages
  • setuptools-rust Setuptools plugin for Rust support.
  • pyo3-built Simple macro to expose metadata obtained with the built crate as a PyDict
  • rust-numpy Rust binding of NumPy C-API
  • dict-derive Derive FromPyObject to automatically transform Python dicts into Rust structs
  • pyo3-log Bridge from Rust to Python logging
  • pythonize Serde serializer for converting Rust objects to JSON-compatible Python objects
  • pyo3-asyncio Utilities for working with Python's Asyncio library and async functions
  • rustimport Directly import Rust files or crates from Python, without manual compilation step. Provides pyo3 integration by default and generates pyo3 binding code automatically.

Examples

  • autopy A simple, cross-platform GUI automation library for Python and Rust.
    • Contains an example of building wheels on TravisCI and appveyor using cibuildwheel
  • ballista-python A Python library that binds to Apache Arrow distributed query engine Ballista.
  • bed-reader Read and write the PLINK BED format, simply and efficiently.
    • Shows Rayon/ndarray::parallel (including capturing errors, controlling thread num), Python types to Rust generics, Github Actions
  • cryptography Python cryptography library with some functionality in Rust.
  • css-inline CSS inlining for Python implemented in Rust.
  • datafusion-python A Python library that binds to Apache Arrow in-memory query engine DataFusion.
  • deltalake-python Native Delta Lake Python binding based on delta-rs with Pandas integration.
  • fastbloom A fast bloom filter | counting bloom filter implemented by Rust for Rust and Python!
  • fastuuid Python bindings to Rust's UUID library.
  • feos Lightning fast thermodynamic modeling in Rust with fully developed Python interface.
  • forust A lightweight gradient boosted decision tree library written in Rust.
  • greptimedb Support Python scripting in the database
  • haem A Python library for working on Bioinformatics problems.
  • html-py-ever Using html5ever through kuchiki to speed up html parsing and css-selecting.
  • hyperjson A hyper-fast Python module for reading/writing JSON data using Rust's serde-json.
  • inline-python Inline Python code directly in your Rust code.
  • johnnycanencrypt OpenPGP library with Yubikey support.
  • jsonschema-rs Fast JSON Schema validation library.
  • mocpy Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere.
  • opendal A data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way.
  • orjson Fast Python JSON library.
  • ormsgpack Fast Python msgpack library.
  • point-process High level API for pointprocesses as a Python library.
  • polaroid Hyper Fast and safe image manipulation library for Python written in Rust.
  • polars Fast multi-threaded DataFrame library in Rust | Python | Node.js.
  • pydantic-core Core validation logic for pydantic written in Rust.
  • pyheck Fast case conversion library, built by wrapping heck.
    • Quite easy to follow as there's not much code.
  • pyre Fast Python HTTP server written in Rust.
  • pyreqwest_impersonate The fastest python HTTP client that can impersonate web browsers by mimicking their headers and TLS/JA3/JA4/HTTP2 fingerprints.
  • ril-py A performant and high-level image processing library for Python written in Rust.
  • river Online machine learning in python, the computationally heavy statistics algorithms are implemented in Rust.
  • rust-python-coverage Example PyO3 project with automated test coverage for Rust and Python.
  • tiktoken A fast BPE tokeniser for use with OpenAI's models.
  • tokenizers Python bindings to the Hugging Face tokenizers (NLP) written in Rust.
  • tzfpy A fast package to convert longitude/latitude to timezone name.
  • utiles Fast Python web-map tile utilities
  • wasmer-python Python library to run WebAssembly binaries.

Articles and other media

Contributing

Everyone is welcomed to contribute to PyO3! There are many ways to support the project, such as:

  • help PyO3 users with issues on GitHub and Discord
  • improve documentation
  • write features and bugfixes
  • publish blogs and examples of how to use PyO3

Our contributing notes and architecture guide have more resources if you wish to volunteer time for PyO3 and are searching where to start.

If you don't have time to contribute yourself but still wish to support the project's future success, some of our maintainers have GitHub sponsorship pages:

License

PyO3 is licensed under the Apache-2.0 license or the MIT license, at your option.

Python is licensed under the Python License.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in PyO3 by you, as defined in the Apache License, shall be dual-licensed as above, without any additional terms or conditions.

Deploys by Netlify

maturin's People

Contributors

badboy avatar bors[bot] avatar cclauss avatar clbarnes avatar davidhewitt avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar hombit avatar hoodmane avatar idavis avatar ijl avatar ischaojie avatar jasperdesutter avatar kngwyu avatar konstin avatar kxepal avatar lenqth avatar mbargull avatar mbrobbel avatar mbway avatar messense avatar mhils avatar niyas-sait avatar paddyhoran avatar pre-commit-ci[bot] avatar programmerjake avatar ravenexp avatar xuanwo avatar yushiomote avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

maturin's Issues

manylinux docker image issues

I've tried the official docker image with pyo3 0.6.0, and the master with pyo3 0.7.0 alpha1.

It seems to always complain about missing libpython.

Running it like this:
docker run --rm -v (pwd):/io 10c0135f4da7 build (10c0135f4da7 being master version of docker image)

๐Ÿ”— Found pyo3 bindings
๐Ÿ Found CPython 3.5m at python3.5, CPython 3.6m at python3.6, CPython 3.7m at python3.7
   Compiling pyo3 v0.7.0-alpha.1
error: could not find native static library `python3.5m`, perhaps an -L flag is missing?


error: aborting due to previous error


error: Could not compile `pyo3`.

To learn more, run the command again with --verbose.
Cargo build finished with "exit code: 101": `cargo rustc --message-format json --manifest-path Cargo.toml --features pyo3/python3 --lib --`
Failed to build a native library through cargo

It seems from a quick glace inside the container that libpython is nowhere to be found.

[root@dca866f6dbb7 /]# find . -iname "*libpython*.so*"
./usr/lib64/libpython2.4.so
./usr/lib64/libpython2.4.so.1.0
[root@dca866f6dbb7 /]#

Am I missing something?

Refactor manylinux options

With manylinux 2014 there are now 4 linux flavors (bare linux, manylinux, manylinux200 and manylinux204) and it seems that in the future we will have manylinux releases regularly. To avoid the --manylinux options from becoming overloaded, the --skip-auditwheel should be un-deprecated and the possible values of --manylinux should become off, 1, 2010 and 2014.

PEP440 following CI Versions

Maybe I missed this somewhere, but as far as I can tell pyo3-pack has no support for it:

I'm trying to set up a CI pipeline, both for our in-works stuff with snapshot builds, as well as our release pipeline. Unfortunately, I can't seem to make both pip and Cargo happy at the same time.

To start with, let's stick with a definition of a CI generated build ID. It'll be in the format of {YYYY}{MM}{DD}{MonotonicallyIncreasingDailyBuildNumber}, with the build number being left padded to 3 places, e.g. "20190422003", where today's date is 2019-04-22 and we're on the 3rd build of the day. I'll call this {BuildID} in my examples down below.

From what I can tell, Cargo is adamantly opposed to a {Major}.{Minor}.{Patch}.dev{BuildId}, which is a fair enough pre-release format that complies with PEP440 and pip's --pre flag. Example: 2.1.3.dev20190422003

Unfortunately, the Cargo way of doing CI builds is very strictly in the form of {Major}.{Minor}.{Patch}-{SomeAllowableString}{BuildId} , e.g. 2.1.3-dev20190422003. The hyphen is most important, and it's something Cargo does not seem capable of budging on. And since our version is the came as our version in our Cargo.toml, our wheel gets generated as my_artifact_2.1.3-dev20190422003-cp36-cp36m-manylinux1_x86_64.whl. I can publish this to a snapshot repo, but my_artifact_2.1.3-dev... is not going to work with pip's --pre flag; it just ignores it.

If we were in a mono repo this wouldn't even be close to a problem, but we aren't, so it is. It would be great if we could specify some version metadata that would get appended to the version prior to constructing our wheels. I superficially thought I could just rename the wheel and maybe update some metadata in a pinch, but with the sha256 checksums it looked like it wasn't going to be that straight forward.

Is there any way that you can think of to make pip --pre happy AND Cargo? If not, can we add a flag that simply appends a "fixed" string to the version that pyo3-pack is going to generate with (fixed in that it wouldn't need to be anything special to pyo3-pack - just a string append operation, but something I can construct in our build pipeline and pass in)?

Enable cargo feature when building

Tried using

โฏ pyo3-pack build -b pyo3 --cargo-extra-args --features bridge-python
error: Found argument '--features' which wasn't expected, or isn't valid in this context

Renaming the project

"pyo3-pack" has become a misleading name for this project, as it can now equally package rust-cpython and cffi projects. Prior to the 0.7 release, I want to rename the project into something that better represents the current features, or at least to a neutral name.

Publish 0.6.1 on crates.io

It would be nice if you could publish 0.6.1 on crates.io, right now cargo install pyo3-pack fails because of the yanked structopt version.

Thanks in advance!

Specifying python dependencies

Hi! Thanks for the cool project!

Small question: is it possible to specify external python dependencies in a mixed pyo3-pack project layout? If the python part of a mixed project is dependent on some package, let's say external_package==1.0.0, is there any way of specifying this so that the following command:

pip install my_pyo3_package.whl

will automatically pull in the external_package dependency?

I was thinking about something analogous to the scripts definition in Cargo.toml:

[package.metadata.pyo3-pack.requires-dist]
external_package = "==1.0.0"

but could not find it in the docs. Is this possible?

Use [package] name instead of [lib] name

First of all: awesome project !

Now, here's the mostly subjective part: like crates.io, pypi does not have a strong policy on module naming, but the strong consensus is to use kebab case instead of underscore case. There are 3x more packages with kebab case than with underscore case.

Using the name in [lib] will enforce underscore case, since they must be a valid crate identifier, whereas using the name in [package] allows the package developer to choose whatever case he wants.

Trove classifiers

Thoughts on adding support for trove classifiers for pypi?

Possibly something like:

[package.metadata.pyo3-pack.metadata]
classifier = [
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.7",
]

This is somewhat consistent with the [package.metadata.pyo3-pack.scripts] mentioned in the README.

broken wheels (macOS)

Currently wheels produced with pyo3-pack are not working in macOS (maybe on other platforms as well?).

I initially though this is related to PyO3/pyo3#341, but I've tried reverting to pyo3 0.5.4 and the issue persisted.

I'm using the extension-module feature.

I'm getting the following error:

Python 3.7.3 | packaged by conda-forge | (default, Mar 27 2019, 15:43:19)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import evtx
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define module export function (PyInit_evtx)
>>>

And for wheels setuptools-rust with python setup.py bdist_wheel it's working as expected.

Python 3.7.3 | packaged by conda-forge | (default, Mar 27 2019, 15:43:19)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import evtx
>>>

All the code is public at https://github.com/omerbenamram/pyevtx-rs

Any thoughts?

Bug: Cannot install maturin from PyPI

pip install maturin gets

ERROR: Could not find a version that satisfies the requirement maturin (from versions: )
No matching distribution found for maturin

using pip 19.2.3, python 3.7.3. Same result if I look specifically for version 0.7.0, but with from versions: none. If I try to pip install . my package, pip tries to install maturin based on build-system.requires, and hits the same error, but with from versions: 0.7.1b1.

I can cargo install it fine, but then pip can't pick it up from the pyproject.toml.

pyo3_mixed not working properly on macOS

When running pyo3-pack develop in the test_crates/pyo3-mixed directory, a dynamic library is placed in the site-packages but the python module is left unused. This also holds for pyo3-pack build then pip install target/wheels/* -- the rust extension is able to be imported properly with import pyo3_mixed but the get_42() function call is not available (rust function get_21() works however).

I'm having the same issue with my own project developed with pyo3-pack. I haven't yet had the chance to check running this on linux.

Mixed project layout

This layout makes it possible to combine a python project with a native rust extension. The minimal structure would look like the following:

my_proj
  src
    lib.rs
  my_proj
    __init__.py
  Cargo.toml

pyo3-pack would add either the shared library (for pyo3 and rust-cpython) or a folder with the shared library and some glue code (for cffi) in __init__.py in the my_proj/my_proj directoy. The module is named after the lib name in the Cargo.toml.

It should be possible to auto-detect this layout. It would also fix the problem of adding a .pyi file.

pyo3-pack does not compile, because structopt 0.2.17 was yanked

error: failed to compile `pyo3-pack v0.6.0`, intermediate artifacts can be found at `/tmp/cargo-installibhtoX`
Caused by:
  failed to select a version for the requirement `structopt = "^0.2.17"`
  candidate versions found which didn't match: 0.2.16, 0.2.15, 0.2.14, ...
  location searched: crates.io index
required by package `pyo3-pack v0.6.0`

See: TeXitoi/structopt#200

Installation of beta release

Ubuntu 16.04, python 3.7.3, rustc 1.37.0-nightly (02564de47 2019-06-10), cargo 1.37.0-nightly (545f35425 2019-05-23)

  • Installing from source (download github release tarball -> pip install .) says it can't find the build backend (it does seem to rely on itself in the pyproject.toml [1])
  • Trying to pip install from github does the same
  • Installing from the deb places a file called pyo3-pack in /usr/bin/. The file exists, is executable, and is picked up by which. Trying to use it gives "command not found" in zsh and "No such file or directory" in bash
  • Downloading the binary gz and placing it somewhere on the path: same as above

[1] trying to bootstrap with an earlier release doesn't help

Source distribution of pyo3-pack

Would it be possible to provide a source distribution of pyo3-pack? Pipenv cannot install it on NixOS which is not manylinux-compatible.

Add option to pass python version number

When building through a CI pipeline, it's not possible to pass a version number that has an incremental build number to maturin build.
For my use case, the rust package has version "0.3.0", but the actual python package/wheel should receive "0.3.0.dev50". Simply renaming the file is not enough as the embedded metadata contains the version in some places (including directory name).
Passing the version would need to be dynamic - through environment variable or argument, not in a file like Cargo.toml - because this version is generated by the build pipeline.

Also note that cargo version semantics are different to python, and treats "0.3.0.dev50" as junk.

Support Metadata-Version in package.metadata.pyo3-pack

First off, I have to use artifactory which does not support Metadata-Version higher than 2.0, so this strange feature request stems from that.

In the Python metadata section the docs state "You can use other fields from the python core metadata in the [package.metadata.pyo3-pack] section (...)". I was somehow expecting I could override/set the Metadata-Version in this way by declaring something like:

[package.metadata.pyo3-pack]
metadata-version = "2.0"

Does this make sense to support? If you point me to the right direction I can try to do a PR myself.

__version__

It would be cool if pyo3-pack packages defined their version to be the one from cargo.toml automatically.

In the meanwhile, how would I define such a static string for my pymodule?

Installation of scripts

I have tried out the Python/Rust example in the pyo3_mixed folder and I noticed that maturin develop does not install the script declared in Cargo.toml. Is this the intended behavior?

publish 0.7.5 completely

It appears as though version 0.7.5 didn't end up on pypi for non-windows platforms:
https://pypi.org/project/maturin/0.7.5/#files

I think there should also be a source package on pypi for those who are using non-x86 platforms, if that's doable (not sure if pypi shows that in the files tab).

Also, 0.7.5 didn't end up on crates.io at all.

Full PyPy support

pyo3-pack gets basic pypy support from #105, while some things are still missing.

  • Add some automated testing, ideally on ci as pyo3 does.
  • Figure out the best way to deal with manylinux.
  • Add windows support
    • Find a reference how a native pypy wheel on windows should look like: python_Levenshtein-0.10.2-pp38-pypy38_pp73-win_amd64.whl contains Levenshtein.pypy38-pp73-win_amd64.pyd: https://paste.rs/ZAJ
  • Test on mac (done by @messense, it works)
  • Skip pypy wheels when uploading
  • Autodetect pypy binaries, but only for pyo3
  • Look for a better way than using SOABI to determine the native extensions filename since that value isn't define on windows for both cpython and pypy. SOABI is defined on windows for at least pypy 3.7 and later.
  • #460

Feature request: Do not build wheels for python versions not supported by package

My computer has more versions of python installed on it than my pyo3-based library supports. maturin build should not build wheels for unsupported python versions. Of course, it's possible to specify exactly which versions to build on every call to maturin build, but that's a relatively static item of metadata which is a good fit for a config file (probably the Cargo.toml, although possibly pyproject.toml).

One option would be to parse the trove classifiers specified in package.metadata.maturin.classifier package.metadata.maturin.requires-python, and build wheels for the intersection of what maturin supports and what is specified there.

Readme.md

So I've successfully written and published my first python-rust module with pyo3 and pyo3-pack, and it's been a pretty painless process (and I thank you for that!).
Als, pypi does not show my Readme.md (or an README.md for that matter).

Is this not supported (yet) or am I doing something wrong?

I published with pyo3-pack publish,
this is the github: https://github.com/TyberiusPrime/mbf_gtf
and the pypi packages can be seen here https://pypi.org/project/mbf_gtf/

pyo3-pack fails if no python3 executable is present

If pyo3-pack develop is called and no interpreter named python3 is present the setup fails:

(venv) PS D:\Entwicklung\Rust\python-extension> pyo3-pack.exe develop
๐Ÿ”— Found pyo3 bindings
python3 doesn't exist

After creating a copy of python.exe with the name python3.exe the call was successful.

System Information:

  • Windows 10
  • Python 3.7.2 64bit in a virtualenv
  • pyo3-pack 0.6.1

Error with passing flag as rustc extra arg.

The Readme says:

--rustc-extra-args <rustc_extra_args>...
           Extra arguments that will be passed to rustc as `cargo rustc [...] -- [arg1] [arg2]`

If I run

pyo3-pack build --rustc-extra-args -Awarnings

I get an error

error: Found argument '-A' which wasn't expected, ...

Is passing flags and options as arguments not supported? Otherwise how am I supposed to pass them?

Build crate where pyo3 is enabled by a feature

I'm trying to add python bindings to an already-existing crate where I want python to be enabled with a feature that is not enabled by default. I created a minimal example of what I wanted to do:
https://github.com/programmerjake/rust-python-test/tree/7b7ac59c66df8c5b8939361f94f2bc92c53b3c4b

Building using cargo works just fine with:

$ cargo +nightly build --features python-extension

I tried to build it using maturin 0.7.2 running in the repo root directory but it didn't work:

$ maturin build
๐Ÿ’ฅ maturin failed
  Caused by: Couldn't find any bindings; Please specify them with --bindings/-b

I also tried:

$ maturin build --bindings=pyo3
๐Ÿ’ฅ maturin failed
  Caused by: The bindings crate pyo3 was not found in the dependencies list
$ maturin build --bindings=pyo3 --cargo-extra-args="--features python-extension"
๐Ÿ’ฅ maturin failed
  Caused by: The bindings crate pyo3 was not found in the dependencies list
$ maturin build --cargo-extra-args="--features python-extension"
๐Ÿ’ฅ maturin failed
  Caused by: Couldn't find any bindings; Please specify them with --bindings/-b

How do I fix it?

Manylinux2010 does not seem to be correctly supported

I built a wheel for manylinux2010 using pyo3-pack.

After I built it I run auditwheel myself and I was surprised by the result:

fastuuid-0.1.0-cp35-cp35m-manylinux2010_x86_64.whl is consistent with
the following platform tag: "manylinux1_x86_64".

I am building that wheel using the manylinux2010 docker image so I'm supposed to get a manylinux2010 wheel.

Either auditwheel is wrong or we are not doing something we should be doing.
What do you think?

Windows and Mac testing

pyo3-pack is meant as a replacement for setuptools-rust and is as such feature complete. As I'm working primarily on linux, I did only very limited tests on windows and don't have any mac to test on. It'd appreciate help testing those platforms.

To install pyo3-pack, you can use a prebuilt binary or cargo install pyo3-pack. For testing you can take any pyo3-powered python extension (e.g. hyperjson, pyo3's example or rust-numpy's example), build it, install it with pip and check if you can import it. I'd also be interested in feedback on the user experience (e.g. incomprehensible error message that showed up).

CC @althonos @mre @fafhrd91

Custom package namespace

Note I am not talking about the distribution name (packages are names you import, distributions those you pip install).

Distutils based tools support an argument ext_package which makes extension modules installed in a prefix package. Perhaps this could be supported in some way? I don't like polluting the global namespace.

Clarification on the manylinux wheels comliance

Thanks for this very useful package!

Regarding building manylinux1 wheels, the readme states,

The pypa offers a special docker container and a tool called auditwheel to ensure compliance with the manylinux rules. pyo3-pack contains a reimplementation of the most important part of auditwheel that checks the generated library, so there's no need to use external tools. If you want to disable the manylinux compliance checks for some reason, use the --skip-auditwheel flag.

As far as I understand, another requirement of the manylinux policy is that it needs to work with CentOS 5.11 (on which those docker images are based). Does it mean that one has to use these docker images (and install rust nightly there)? The readme sounds like it's not necessary...

Support non-manylinux Linux builds

Linux builds should be able to target their specific installation rather than the manylinux1 target. Maybe a flag of --env-specific or something better named, which implies --skip-auditwheel, and generates the ...-cp37-cp37m-linux_x86_64.whl tag?

Feature request: option to build no wheels (sdist only)

On CI, where only one python version is available per job, it might be preferable to have one job per wheel. In that case, you wouldn't also want to try (and fail) to deploy one sdist per job. You could read some environment variables and mangle your maturin arguments to do --no-sdist in specific situations, but it might be more ergonomic to run one job which is just an sdist, and one job for each wheel.

I suggest -I (upper-case i)/--sdist-only, as it's the opposite of adding an interpreter to build a wheel for with -i.

Detect cffi and bin targets automatically

Currently, only rust-cpython and pyo3 are automatically detected. For cffi and bin, you need to use the -b flag. In many it should be possible to decide that automatically based on whether the crate has a cdylib or bin target.

Relevant excerpts from cargo metadata for a cffi and a bin crate:

         "targets" : [
            {
               "src_path" : "/home/konsti/bin-test/src/main.rs",
               "edition" : "2018",
               "kind" : [
                  "bin"
               ],
               "crate_types" : [
                  "bin"
               ],
               "name" : "a"
            }
         ]
         "targets" : [
            {
               "crate_types" : [
                  "cdylib"
               ],
               "edition" : "2018",
               "src_path" : "/home/konsti/lib-test/src/lib.rs",
               "name" : "lib-test",
               "kind" : [
                  "cdylib"
               ]
            }
         ],

Include files

I'd like to include a file in the built wheel. How about packaging anything in a project's Cargo.toml include array?

PEP 517 integration

The recent PEP 517 specifies an interface for alternative build systems to be defined, which is exactly what's happening here.

To do that, pyo3-pack would need to provide a very simple Python interface with the following hooks:

  • build_wheel to build a wheel
  • build_sdist to build a gztarred archive of the source code
    (actual semantics are defined in the PEP).

Then, releasing the pyo3-pack module to PyPI would allow users to specify the build system in pyproject.toml, making it easier to build a Rust wheel without setuptools.

Mixed projects PYTHONPATH issue

maturin builds a mixed Rust/Python project if {name}/__init__.py exists, so the PYTHONPATH for the project's name is this directory rather than the installed project. This causes ImportError in tests etc. during development. This affects all mixed projects, so perhaps the detection can instead use _{name}/__init__.py or py{name}/__init__.py? I see that the directory could also be an option in Cargo.toml but I think it would be better to fix by default.

Collecting extra file use cases

For some projects it's necessary to add more files than those generated by pyo3-pack. Doing this is more difficult than for pure python projects because we don't have a classic source directory we just copy over. We also can't use cargo's includes/exclude because they might only be valid for the rust package. This issue is meant to collect what cases need to be considered.

If you have a usecase where you need to add extra files, please add it here. Information about whether the file is in the cargo includes/excludes and where it should go when installing the wheel (or where it should be inside the wheel) would be helpful.

Unable to pip install mixed layout project

There seems to be a problem with pip installing a mixed layout project where it doesn't place the compiled rust code into the project folder.

I made the following changes to pyo3-pack:

  • in "pyo3-pack/test-crates/pyo3-mixed/pyproject.toml" I changed requires = ["pyo3-pack"] to requires = ["pyo3-pack==0.7.0-beta.7"]
  • in "pyo3-pack/test-crates/pyo3-mixed/rust-toolchain" I changed nightly to nightly-2019-07-01 since I couldn't get mashup to compile on the most recent nightly.

Using this setup I cd'd into the pyo3-mixed test crate and ran pip install .
This runs without an error, however when I open python and try to import pyo3_mixed I get the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pattonw/Work/Packages/pyo3-pack/test-crates/pyo3-mixed/pyo3_mixed/__init__.py", line 2, in <module>
    from .pyo3_mixed import get_21
ModuleNotFoundError: No module named 'pyo3_mixed.pyo3_mixed'

This seems like it can't find the python functions created by rust in they python code directory, so I ran pyo3-pack develop which created the file "pyo3-pack/test-crates/pyo3-imxed/pyo3_mixed/pyo3_mixed.cpython-37m-x86_64-linux-gnu.so"

With this file created, pip install ., import pyo3_mixed, and pyo3_mixed.get_42() all work as expected.

platform mismatch for cross compilation

When compiling a cffi crate for a different target through a Cargo environment which has been setup for cross-compilation, maturin fails on a platform check.
I'm trying to build a windows cffi package from a linux build system, but maturin tries to get the windows python.exe, which can easily be overruled by the -i flag. But when passed a linux python version, maturin crashes with this output:

$ maturin build -b cffi --target x86_64-pc-windows-gnu -i python3.7

๐Ÿน Building a mixed python/rust project
๐Ÿ’ฅ maturin failed
  Caused by: Failed to find python interpreter for generating cffi bindings
  Caused by: Failed to get information from the python interpreter at python3.7
  Caused by: sys.platform in python, linux, and the rust target, Target { os: Windows, is_64_bit: true }, don't match เฒ _เฒ 

I can manually replace the native.so file within the built wheel by a built windows dll file and it works fine on windows. So I'm guessing this is just a limitation within maturin currently.
This check doesn't seem necessary for me, but could probably be wrong for other use-cases. Does it seem feasible to change this behavior?

Does not handle conda environments on windows

Many windows users use conda environments to manage their python versions. pyo3-pack does not seem to handle them well.

pyo3-pack develop mentions that I should be in a venv, but I am in a virtual environment. It's just that I am using conda not venv.

pyo3-pack relies on the python launcher, which is not installed with conda (there is a standalone installer but it does not seem to play nice with conda). The information regarding available interpreters can be gotten from conda info -e

How to generate windows wheels?

Hello, first of all let me tell you this project is really nice, 1 command will produce wheels... Before this I'd tried setuptools-rust and the process was quite tricky :/

Anyway, got a couple of questions, right now I've been able to generate wheels for linux by using the undocummented --release suffix using a command like:

`docker run -it -v `pwd`:/io konstin2/pyo3-pack build`

And the above command has generated me 4 wheels:

pysyntect-0.0.1-cp27-cp27mu-manylinux1_x86_64.whl
pysyntect-0.0.1-cp35-cp35m-manylinux1_x86_64.whl
pysyntect-0.0.1-cp36-cp36m-manylinux1_x86_64.whl
pysyntect-0.0.1-cp37-cp37m-manylinux1_x86_64.whl

1st issue

So far so good... Now I was trying to figure out how to do the same on windows7 but some errors have appeared... take a look:

(py364_32) D:\sources\personal\python\pysyntect>pyo3-pack list-python
Could not find any interpreters, are you sure you have python installed on your PATH?

(py364_32) D:\sources\personal\python\pysyntect>pyo3-pack build
๐Ÿ”— Found pyo3 bindings
Could not find any interpreters, are you sure you have python installed on your PATH?

As you can see, I'm calling pyo3-pack build from my activated virtualenv (python is on PATH!!!).

2nd issue

I would be interested to generate wheels for windows/linux && cp36-cp36m... that's all, the rest of platforms (cp27,cp35,cp37) are pretty much irrelevant to me, isn't possible to specify that somehow to pyo3-pack?

Thanks in advance!

Ps. Isn't there any irc channel on freenode/moznet to discuss stuff about pyo3, setuptools-rust, pyo3-pack? I see there is gitter... but I prefer using IRC ;)

Improvements for build.rs usage

I have a project that has a custom build.rs script. Ideally, pyo3-pack would be able to pass the information about the interpreter being used to compile the rust crate to the script, so that any additional library needing to include/link to CPython can re-use this information and I don't need to re-compute it.

Perhaps it can be passed as environment variables when invoking cargo?

Precompiled 0.6.1 binary not working on Ubuntu 18.04

wget https://github.com/PyO3/maturin/releases/download/v0.6.1/pyo3-pack-v0.6.1-x86_64-unknown-linux-musl.tar.gz
tar -xzf pyo3-pack-v0.6.1-x86_64-unknown-linux-musl.tar.gz
./pyo3-pack

fails with

zsh: no such file or directory: ./pyo3-pack
wget https://github.com/PyO3/maturin/releases/download/v0.7.2/maturin-v0.7.2-x86_64-unknown-linux-musl.tar.gz
tar -xzf maturin-v0.7.2-x86_64-unknown-linux-musl.tar.gz
./maturin

prints usage as expected:

maturin 0.7.2
Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages

USAGE:
    maturin <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    build          Build the crate into python packages
    develop        Installs the crate as module in the current virtualenv
    help           Prints this message or the help of the given subcommand(s)
    list-python    Searches and lists the available python installations
    pep517         Backend for the PEP 517 integration. Not for human consumption
    publish        Build and publish the crate as python packages to pypi
    sdist          Build only a source distribution (sdist) without compiling

Fwiw, downloading and installing the .deb file through dpkg leads to the same behaviour.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.