2

With the move to the new pyproject.toml system, I was wondering whether there was a way to install packages in editable mode while compiling extensions (which pip install -e . does not do).

So I want pip to:

  • run the build_ext I configured for Cython and generate my .so files
  • put them in the local folder
  • do the rest of the normal editable install

I found some mentions of build_wheel_for_editable on the pip documentation but I could not find any actual example of where this hook should be implemented and what it should look like. (to be honest, I'm not even completely sure this is what I'm looking for)

So would anyone know how to do that? I'd also happy about any additional explanation as to why pip install . runs build_ext but the editable command does not.


Details:

I don't have a setup.py file anymore; the pyproject.toml uses setuptools and contains

[build-system]
requires = ["setuptools>=61.0", "numpy>=1.17", "cython>=0.18"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
package-dir = {"" = "."}

[tool.setuptools.packages]
find = {}

[tool.setuptools.cmdclass]
build_ext = "_custom_build.build_ext"

The custom build_ext looks like

from setuptools import Extension
from setuptools.command.build_ext import build_ext as _build_ext

from Cython.Build import cythonize

class build_ext(_build_ext):

    def initialize_options(self):
        super().initialize_options()
        if self.distribution.ext_modules is None:
            self.distribution.ext_modules = []
        extensions = Extension(...)
        self.distribution.ext_modules.extend(cythonize(extensions))

    def build_extensions(self):
        ...
        super().build_extensions()

It builds a .pyx into .cpp, then adds it with another cpp into a .so.

Silmathoron
  • 1,781
  • 1
  • 15
  • 32
  • I'm pretty sure if you use setuptools and the cythonize script this will "just work". Can you share more detail about how you're building your project, e.g. which build backend you're using. – ngoldbaum Feb 16 '23 at 17:28
  • I added the gist of the two main files; as mentioned in the post, `pip install .` compiles the cython files but `pip install -e .` does not – Silmathoron Feb 16 '23 at 21:42
  • 1
    If you add `_custom_build.py` to the `py-modules` then I think it will also be added to the wheel and then installed on the end-users machines. This seems like it is not what you want -- Aside: I feel like I have already said the exact same thing on another question, so much so that I am really wondering if you both got inspired fro the same misleading source. – sinoroc Feb 20 '23 at 13:35
  • I mixed a lot of things in there, but that specific mistake probably came from https://stackoverflow.com/a/74196312/5962321 – Silmathoron Feb 20 '23 at 14:05

1 Answers1

3

I created a module that looks like this:

$  tree .   
.
├── pyproject.toml
├── setup.py
└── test
    └── helloworld.pyx

1 directory, 3 files

My pyproject.toml looks like:

[build-system]
requires = ["setuptools>=61.0", "numpy>=1.17", "cython>=0.18"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
py-modules = ["test"]

[project]
name        = "test"
version     = "0.0.1"%    

My setup.py:

from setuptools import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize("test/helloworld.pyx"))

And helloworld.pyx just contains print("Hello world").

When I do pip install -e ., it builds the cython file as expected.

If you really don't want to have a setup.py at all, I think you'll need to override build_py instead of build_ext, but IMO just having the simple setup.py file isn't a big deal.

ngoldbaum
  • 5,430
  • 3
  • 28
  • 35
  • 1
    Interesting, to be honest, I just assumed from the new pip messages and a quick glance at the pyproject.toml rationale that I had to delete the setup.py altogether. I guess it feels a bit hacky to have both, though it's not a big deal... I kind of feel like the toml file should be self-sufficient, but I'll get over it ^^ – Silmathoron Feb 18 '23 at 07:30
  • 2
    Nothing wrong at all with having the packaging metadata in the `[project]` section of `pyproject.toml` while still keeping a `setup.cfg` and/or a `setup.py` for the things that do not fit in `[project]`. And the custom build steps is definitely one of those things. `[project]` is really only meant for the metadata, and what you need has nothing to do with metadata as far as I understood. See here for example: https://setuptools.pypa.io/en/latest/userguide/ext_modules.html – sinoroc Feb 20 '23 at 13:31
  • 1
    I'm a bit confused then: if the toml file is only for metadata, why can I set ``build_ext`` in ``[tool.setuptools.cmdclass]``? That's not really metadata, is it? Anyway, that really made me think that the goal was to remove ``setup.py`` altogether – Silmathoron Feb 20 '23 at 14:08
  • Honest Question: Is there really no way to make a `pyproject.toml` work without having a `setup.x` file? The whole reason I care about `pyproject.toml` is the Python org is forcing us to move away from `setup.py`. If I still need a `setup.py` anyway, what's the point? – john_science Sep 01 '23 at 01:04