Tyrick
Tyrick

Reputation: 2966

Customizing python package directory layout with setup.py

Suppose I have the following directory structure:

src/
└── python/
    └── generated/
        ├── __init__.py
        ├── a.py
        └── lib/
            ├── __init__.py
            └── b.py

What does my setup.py need to look like in order to create a dist with a directory layout like:

src/
└── python/
    ├── __init__.py
    ├── a.py
    └── lib/
        ├── __init__.py
        └── b.py

The goal is to simply eliminate the generated folder. I've tried endless variations with package_dir and can't get anything produced other than the original directory structure.

Upvotes: 6

Views: 5820

Answers (2)

sinoroc
sinoroc

Reputation: 22295

In this specific case, for this specific project directory structure, the setup.py script should be placed in the src directory and should look like this:

#!/usr/bin/env python
    
import setuptools
    
setuptools.setup(
    name='Thing',
    version='1.2.3',
    packages=[
        'python',
        'python.lib',
    ],
    package_dir={
        'python': 'python/generated',
    },
)

Note the package_dir setting. It instructs setuptools to get the code for the python package from the directory python/generated. In the built distributions you will then find the right directory structure.

Upvotes: 6

FLemaitre
FLemaitre

Reputation: 511

First, here is my solution:

#!/usr/bin/env python

import os, shutil
from setuptools import setup
from setuptools.command.build_py import build_py

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

  def run(self):
    shutil.rmtree('src.tmp', ignore_errors=True)
    os.mkdir('src.tmp')
    shutil.copytree('src/python/generated', 'src.tmp/python')
    build_py.run(self)

setup(cmdclass={ 'build_py': BuildPyCommand },
      name='Blabla',
      version='1.0',
      description='best desc ever',
      author='Me',
      packages=['python', 'python.lib'],
      package_dir={'': 'src.tmp'},
      setup_requires=['wheel']
     )

And you can generate your distribution with:

python setup.py build bdist_wheel

The idea is perform a two steps build:

  • I generate a valid source structure
  • I build this temporary structure

And I deliver it in a wheel because it doesn't require future users to understand my trick. If you give it a try with a source distribution, you will notice that you need to publish the generated files as data (not difficult, but troublesome, and, I guess you will want to hide your tricks from your users).

But, I think that there is a design flaw in your process. The file src/python/generated/__init__.py, assumed to be a module <something>.generated eventually becomes your <something>.python, which is troublesome. It would be much simpler and more robust to generate a valid Python structure: src/generated/python/__init__.py. The setup.py would become trivial and your generator wouldn't be more complex.

Upvotes: 0

Related Questions