Skip to content Skip to sidebar Skip to footer

Place Pre-compiled Extensions In Root Folder Of Non-pure Python Wheel Package

TL;DR How do you get distutils/setuptools to include a non-pure data file correctly? I've got a project that does some non-trivial code generation using a custom toolchain, and the

Solution 1:

This works. distutils and setuptools have to be some of the worst designed pieces of central Python infrastructure that exist.

from setuptools import setup, find_packages, Extension
from setuptools.command.build_ext import build_ext
import os
import pathlib
import shutil

suffix = '.pyd' if os.name == 'nt' else '.so'

class CustomDistribution(Distribution):
  def iter_distribution_names(self):
    for pkg in self.packages or ():
      yield pkg
    for module in self.py_modules or ():
      yield module

class CustomExtension(Extension):
  def __init__(self, path):
    self.path = path
    super().__init__(pathlib.PurePath(path).name, [])

class build_CustomExtensions(build_ext):
  def run(self):
    for ext in (x for x in self.extensions if isinstance(x, CustomExtension)):
      source = f"{ext.path}{suffix}"
      build_dir = pathlib.PurePath(self.get_ext_fullpath(ext.name)).parent
      os.makedirs(f"{build_dir}/{pathlib.PurePath(ext.path).parent}",
          exist_ok = True)
      shutil.copy(f"{source}", f"{build_dir}/{source}")

def find_extensions(directory):
  extensions = []
  for path, _, filenames in os.walk(directory):
    for filename in filenames:
      filename = pathlib.PurePath(filename)
      if pathlib.PurePath(filename).suffix == suffix:
        extensions.append(CustomExtension(os.path.join(path, filename.stem)))
  return extensions

setup(
  # Stuff
  ext_modules = find_extensions("PackageRoot"),
  cmdclass = {'build_ext': build_CustomExtensions}
  distclass = CustomDistribution
)

I'm copying extensions into the build directory, and that's it. We override the distribution to lie to the egg-info writers about having any extensions, and everything is gravy.


Post a Comment for "Place Pre-compiled Extensions In Root Folder Of Non-pure Python Wheel Package"