Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's distutils' equivalent of setuptools' `find_packages`? (python)

I have a setup.py file that checks if the user has setuptools and if he doesn't, then I am forced to use distutils. The thing is that, to make sure the submodules are installed, I use setuptools' find package:

from setuptools import setup, find_packages
packages = find_packages()

and then proceed from there.

However, I'm not sure how to do that with distutils. Is there an equivalent function or do I have to manually look for subdirs that have an __init__.py inside of them? If that is the case, is it acceptable for me to require setuptools to install my package and just forget about distutils?

Cheers.

like image 529
TomCho Avatar asked May 20 '16 15:05

TomCho


People also ask

What can I use instead of distutils?

Most Python users will not want to use this module directly, but instead use the cross-version tools maintained by the Python Packaging Authority. In particular, setuptools is an enhanced alternative to distutils that provides: support for declaring project dependencies.

Does Python come with setuptools?

Even in a vanilla version of Python 3.7. 6 (installed via pyenv ), the packages installed by default are both pip and setuptools .

Is Distutils deprecated?

distutils has been deprecated in NumPy 1.23. 0 . It will be removed for Python 3.12; for Python <= 3.11 it will not be removed until 2 years after the Python 3.12 release (Oct 2025).

What is Find_packages in setuptools?

Function defined in setuptools find_packages(where='.', exclude=()) Return a list all Python packages found within directory 'where' 'where' should be supplied as a “cross-platform” (i.e. URL-style) path; it will be converted to the appropriate local path syntax.


1 Answers

It is perfectly acceptable to use setuptools; the vast majority of packages on PyPI already do.

If you want to re-invent the find_packages() wheel, then yes, look for directories with __init__.py files in them. This is what the setuptools.PackageFinder class does. A simplified re-implementation would be:

import os
from distutils.util import convert_path


def find_packages(base_path):
    base_path = convert_path(base_path)
    found = []
    for root, dirs, files in os.walk(base_path, followlinks=True):
        dirs[:] = [d for d in dirs if d[0] != '.' and d not in ('ez_setup', '__pycache__')]
        relpath = os.path.relpath(root, base_path)
        parent = relpath.replace(os.sep, '.').lstrip('.')
        if relpath != '.' and parent not in found:
            # foo.bar package but no foo package, skip
            continue
        for dir in dirs:
            if os.path.isfile(os.path.join(root, dir, '__init__.py')):
                package = '.'.join((parent, dir)) if parent else dir
                found.append(package)
    return found

This ignores the include and exclude arguments of setuptools.find_packages().

like image 190
Martijn Pieters Avatar answered Oct 03 '22 00:10

Martijn Pieters