1

I am attempting to build a python wheel using setuptools. The package needs to include two files:

  • mymodule.py - a python module in the same directory as setup.py
  • myjar.jar - a java .jar file that exists outside of my package directory

I am building my package using python3 setup.py bdist_wheel.

If I call setup() like so:

setup(
    name="mypkg",
    py_modules=["mymodule"],
    data_files=[('jars', ['../target/scala-2.11/myjar.jar'])]
)

then myjar.jar does successfully get included in the .whl (good so far) however when I pip install mypkg it places the jar at /usr/local/myjar.jar (this kinda explains why) which isn't what I want at all, I want it to exist in the same place as mymodule.py, i.e. /usr/local/lib/python3.7/site-packages/

If I change setup.py to

setup(
    name="mypkg",
    py_modules=["mymodule"],
    package_data={'jars': '../target/scala-2.11/myjar.jar'}
)

or

setup(
    name="mypkg",
    py_modules=["mymodule"],
    package_data={'jars': ['../target/scala-2.11/myjar.jar']}
)

then myjar.jar simply doesn't get included in the .whl. I tried copying myjar.jar into the same directory and changing setup.py to:

setup(
    name="mypkg",
    py_modules=["mymodule"],
    package_data={'jars': 'myjar.jar'}
)

or

setup(
    name="mypkg",
    py_modules=["mymodule"],
    package_data={'jars': ['myjar.jar']}
)

but still myjar.jar does not get included in the .whl.

I've been tearing my hair out over this for hours, hence why I'm here.

I've read a myriad of SO posts on this:

which suggest different combinations of data_files, package_data, include_package_data=True and/or use of a Manifest.in file but still I can't get this working as I would like, so I'm here hoping someone can advise what I'm doing wrong.

jamiet
  • 10,501
  • 14
  • 80
  • 159
  • 1
    https://sinoroc.gitlab.io/kb/python/package_data.html – sinoroc May 06 '20 at 07:09
  • thanks, that's helped a lot. I've had to restructure my code a lot to match the structure in your article and it now works. I'm now unpicking it bit by bit to move it back to the structure I want and see where it breaks. One key difference is that my code consists of only a module, not a package. Let's see if I can make it work. – jamiet May 06 '20 at 20:41
  • 1
    I see. Basically you should start with the last example (the 5th) you showed. – sinoroc May 06 '20 at 21:38

1 Answers1

7

The data files (in that case myjar.jar) should really be package data files, and as such they should be part of a Python package. So having such files in parent directories makes things much more complicated, but probably not impossible. So let's start with a simpler example. I believe something like the following should work...

Project directory structure:

MyProject
├ MANIFEST.in
├ mymodule.py
├ setup.py
└ myjars
    ├ __init__.py
    └ myjar.jar

MANIFEST.in:

recursive-include myjars *.jar

setup.py:

#!/usr/bin/env python3

import setuptools

setuptools.setup(
    name='MyProject',
    version='1.2.3',
    #
    include_package_data=True,
    packages=['myjars'],
    py_modules=["mymodule"],
)

myjars/__init__.py might not be strictly necessary, but I believe it's better to have it. And as always, an empty __init__.py file is perfectly good enough.

(This assumes the myjars/myjar.jar file exists before the source distribution sdist is built.)

As to dealing with the data files in parent directories, my recommendation would be to simply copy (or symlink) those files before calling setup.py, maybe as part of a shell script or anything like that. There are probably ways to do the copy as part of a custom setuptools command in setup.py, but it's not worth the effort in my opinion, and really it's not part of setup.py's job.

sinoroc
  • 18,409
  • 2
  • 39
  • 70
  • YES! That did it, thank you SO much. And you're right about the symlink as well of course, so i created that. – jamiet May 07 '20 at 19:45