Exclude single source file from python bdist_egg or bdist_wheel
Asked Answered
D

1

8

Background: I have one source file which is responsible for security. In there are magic keys and specific algorithms.

Is it possible to remove a this single source file from a python egg or wheel package?

I already accomplished to ship only binarys with the the egg command.

python setup.py bdist_egg --exclude-source-files

Edit Project structure:

├── setup.py
├── src
|   ├── __init__.py
|   ├── file1.py
|   ├── file2.py
|   ├── file_to_exclude.py

Thanks for your help!

Doubleminded answered 24/5, 2018 at 9:44 Comment(3)
Excluding single modules is tricky. Can you provide your project structure?Astrahan
Hey, Thanks for your help. I updated the post above.Doubleminded
I have updated the answer with a better solution than what I've suggested earlier; if you're still interested, check it out!Astrahan
A
6

Unfortunately, neither distutils nor setuptools provide a possibility to exclude single modules, so you have to work around it.

Update:

I have described a better solution here that mimics the package exclusion setuptools does in find_packages(). You will have to override the build_py command in the setup script that can accept a list of exclude patterns, same as exclude list in find_packages. In your case, it would be:

import fnmatch
from setuptools import find_packages, setup
from setuptools.command.build_py import build_py as build_py_orig


exclude = ['src.file_to_exclude']


class build_py(build_py_orig):

    def find_package_modules(self, package, package_dir):
        modules = super().find_package_modules(package, package_dir)
        return [(pkg, mod, file, ) for (pkg, mod, file, ) in modules
                if not any(fnmatch.fnmatchcase(pkg + '.' + mod, pat=pattern)
                for pattern in exclude)]


setup(
    ...,
    packages=find_packages(),
    cmdclass={'build_py': build_py},
)

I find this to be a much more powerful and distutils-conform solution than the ones below. It also enables one to exclude multiple modules via wildcard matching, for example

exclude = ['src.file*']

will exclude all modules starting with file in src package, or

exclude = ['*.file1']

will exclude file1.py in all packages.

Original answer

put modules to be excluded in a separate package

You can use the fact that setuptools can exclude packages (dirs containing the __init__.py files), but it will require some refactoring. Create a package_to_exclude, put file_to_exclude.py in there and fix all the eventual import errors:

project
├── setup.py
└── src
     ├── __init__.py
     ├── file1.py
     ├── file2.py
     └── package_to_exclude
          ├── __init__.py
          └── file_to_exclude.py

Now you can exclude package_to_exclude in the setup script:

from setuptools import find_packages, setup

setup(
    ...,
    packages=find_packages(exclude=['src.package_to_exclude'])
)

exclude package, add modules to be included via py_modules

If you can't or don't want to move the module in a separate package, you can exclude the src package and add all the modules in src except file_to_exclude in py_modules. Example:

import os
from setuptools import find_packages, setup

excluded_files = ['file_to_exclude.py']
included_modules = ['src.' + os.path.splitext(f)[0]
                    for f in os.listdir('src')
                    if f not in excluded_files]

setup(
    ...,
    packages=find_packages(exclude=['src']),
    py_modules=included_modules,
)
Astrahan answered 24/5, 2018 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.