jbms / sphinx-immaterial

Adaptation of the popular mkdocs-material material design theme to the sphinx documentation system
https://jbms.github.io/sphinx-immaterial/
Other
177 stars 28 forks source link

Editable install no longer runs nodejs build step #249

Open jbms opened 1 year ago

jbms commented 1 year ago

Looks like the issue is that pip install -e . no longer runs the develop command, which is what we were relying on in setup.py to do the nodejs build. It looks like there is a new mechanism that can be used to handle editable builds, but it is not clear to me exactly how to use it:

https://setuptools.pypa.io/en/latest/userguide/extension.html#supporting-sdists-and-editable-installs-in-build-sub-commands

_Originally posted by @jbms in https://github.com/jbms/sphinx-immaterial/pull/247#discussion_r1179906766_

2bndy5 commented 1 year ago

I made some progress on this. Working with the info from the linked docs, I was able to get editable installs to use a setuptools SubCommand. Although, I'm still trying to figure out how to pass a SubCommand option (ie dirty in the following snippet) from CLI.

from pathlib import Path
import subprocess
from setuptools import setup, Command
from setuptools.command.build_py import build_py
from setuptools.command.sdist import sdist
from setuptools.command.build import SubCommand

pkg_root = Path(__file__).parent / "src"

class SrcDistCommand(sdist):
    """Custom build command."""

    def run(self):
        self.run_command("bundle-icons")
        super().run()

class BuildPyCommand(build_py):
    """Custom build command."""

    def run(self):
        self.run_command("bundle-icons")
        super().run()

class BundleCommand(Command, SubCommand):
    """A custom command to run svgo (via nox) on all bundled SVG icons."""

    description = "Copy and optimize SVG files from npm modules."
    user_options = [
        # The format is (long option, short option, description).
        ("dirty", None, "skip bundling icons if they already exist in pkg src"),
    ]

    def initialize_options(self):
        """Set default values for options."""
        # Each user option must be listed here with their default value.
        self.dirty = False

    def finalize_options(self):
        """Post-process options."""
        if (
            self.dirty
            and not Path(pkg_root, "my_pkg", ".icons", "tabler").exists()
        ):
            raise OSError("Building package 'dirty', but no generated SVG files exist!")

    def run(self):
        """Run command."""
        if not self.dirty:
            self.announce("Running nox session: bundle_icons", level=2)
            subprocess.run(["nox", "-s", "bundle_icons"], check=True, shell=True)

# all install info is located in pyproject.toml
setup(
    cmdclass={
        "bundle-icons": BundleCommand,
        "build_py": BuildPyCommand,
        "sdist": SrcDistCommand,
    },
)

The inheriting from both Command and SubCommand seems redundant, but it seems like they were designed to work together.

jbms commented 1 year ago

I think you can't pass options when using pip install.

This is how I fixed this issue for a different project:

https://github.com/google/neuroglancer/commit/dbd8ead221a9088da46bbf8a82e53ca7b4091ceb#diff-60f61ab7a8d1910d86d9fda2261620314edcae5894d5aaa236b821c7256badd7

2bndy5 commented 1 year ago

pip install does have a --install-options arg, but I've been focusing on how to pass the option from pip wheel. Turns out this

pip wheel --config-settings='--build-option=--dirty' -w dist --no-deps .

will pass the --dirty option to the build commands, but since my pkg deps don't support a --dirty build option, I get errors during the "Installing build dependencies" stage; I also tried dirty without the prefixed -- but same error popped up.


TBH, I don't fully follow all the changes in that diff's setup.py file. But I haven't really explored the setuptools internals enough.

I do like this tactic:

        # If building from an sdist, `package.json` won't be present but the
        # bundled files will.

Seems useful if using pypa/build to make dists.

2bndy5 commented 1 year ago

I just found out that setuptools v64.0.2+ will ignore any exceptions raised by custom commands during editable installs: https://github.com/pypa/setuptools/commit/048633afd7d6e4f852766d06c975ad602a035193 👎🏼