Python Packaging with .pth files

2.6k Views Asked by At

I have a suite of packages that are developed together and bundled into one distribution package.

For sake of argument, let's assume I have Good Reasons for organizing my python distribution package in the following way:

SpanishInqProject/
|---SpanishInq/
|     |- weapons/
|     |   |- __init__.py
|     |   |- fear.py
|     |   |- surprise.py    
|     |- expectations/
|     |   |- __init__.py
|     |   |- noone.py
|     |- characters/
|         |- __init__.py
|         |- biggles.py
|         |- cardinal.py
|- tests/
|- setup.py
|- spanish_inq.pth

I've added the path configuration file spanish_inq.pth to add SpanishInq to the sys.path, so I can import weapons, .etc directly.

I want to be able to use setuptools to build wheels and have pip install weapons, expectations and characters inside the SpanishInq directory, but without making SpanishInq a package or namespace.

My setup.py:

  from setuptools import setup, find_packages

  setup(
    name='spanish_inq',
    packages=find_packages(),
    include_package_data=True,       
   )

With a MANIFEST.in file containing:

   spanish_inq.pth

This has been challenging in a couple of ways:

  • pip install has put weapons etc. directly in the site-packages directory, rather than in a SpanishInq dir.
  • my spanish_inq.pth file ends up in the sys.exec_prefix dir, rather than in my site-packages dir, meaning the relative path in it is now useless.

The first problem I was able to sort of solve by turning SpanishInq into a module (which I'm not happy about), but I still want to be able to import weapons etc. without SpanishInq as a namespace, and to do this I need SpanishInq added to the sys.path, which is where I was hoping the .pth file would help...but I can't get it to go where it ought to.

So...

How do I get the .pth file to install into the site-packages dir?

1

There are 1 best solutions below

0
On

This is very similar to setup.py: installing just a pth file? (this question is strictly a superset, in terms of functionality) -- I've adapted the relevant part of my answer there below.


The right thing to do here is to extend setuptools' build_py, and copy the pth file into the directory into the build directory, in the location where setuptools prepares all the files that go into site-packages there.

from setuptools.command.build_py import build_py


class build_py_with_pth_file(build_py):
     """Include the .pth file for this project, in the generated wheel."""

     def run(self):
         super().run()

         destination_in_wheel = "spanish_inq.pth"
         location_in_source_tree = "spanish_inq.pth"
 
         outfile = os.path.join(self.build_lib, destination_in_wheel)
         self.copy_file(location_in_source_tree, outfile, preserve_mode=0)

setup(
   ...,
   cmdclass={"build_py": build_py_with_pth_file},
)