| 1 | # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) | 
|---|
| 2 | # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php | 
|---|
| 3 | # Note: you may want to copy this into your setup.py file verbatim, as | 
|---|
| 4 | # you can't import this from another package, when you don't know if | 
|---|
| 5 | # that package is installed yet. | 
|---|
| 6 |  | 
|---|
| 7 | import os | 
|---|
| 8 | import sys | 
|---|
| 9 | from fnmatch import fnmatchcase | 
|---|
| 10 | from distutils.util import convert_path | 
|---|
| 11 |  | 
|---|
| 12 | # Provided as an attribute, so you can append to these instead | 
|---|
| 13 | # of replicating them: | 
|---|
| 14 | standard_exclude = ('*.py', '*.pyc', '*~', '.*', '*.bak') | 
|---|
| 15 | standard_exclude_directories = ('.*', 'CVS', '_darcs', './build', | 
|---|
| 16 | './dist', 'EGG-INFO', '*.egg-info') | 
|---|
| 17 |  | 
|---|
| 18 | def find_package_data( | 
|---|
| 19 | where='.', package='', | 
|---|
| 20 | exclude=standard_exclude, | 
|---|
| 21 | exclude_directories=standard_exclude_directories, | 
|---|
| 22 | only_in_packages=True, | 
|---|
| 23 | show_ignored=False): | 
|---|
| 24 | """ | 
|---|
| 25 | Return a dictionary suitable for use in ``package_data`` | 
|---|
| 26 | in a distutils ``setup.py`` file. | 
|---|
| 27 |  | 
|---|
| 28 | The dictionary looks like:: | 
|---|
| 29 |  | 
|---|
| 30 | {'package': [files]} | 
|---|
| 31 |  | 
|---|
| 32 | Where ``files`` is a list of all the files in that package that | 
|---|
| 33 | don't match anything in ``exclude``. | 
|---|
| 34 |  | 
|---|
| 35 | If ``only_in_packages`` is true, then top-level directories that | 
|---|
| 36 | are not packages won't be included (but directories under packages | 
|---|
| 37 | will). | 
|---|
| 38 |  | 
|---|
| 39 | Directories matching any pattern in ``exclude_directories`` will | 
|---|
| 40 | be ignored; by default directories with leading ``.``, ``CVS``, | 
|---|
| 41 | and ``_darcs`` will be ignored. | 
|---|
| 42 |  | 
|---|
| 43 | If ``show_ignored`` is true, then all the files that aren't | 
|---|
| 44 | included in package data are shown on stderr (for debugging | 
|---|
| 45 | purposes). | 
|---|
| 46 |  | 
|---|
| 47 | Note patterns use wildcards, or can be exact paths (including | 
|---|
| 48 | leading ``./``), and all searching is case-insensitive. | 
|---|
| 49 | """ | 
|---|
| 50 |  | 
|---|
| 51 | out = {} | 
|---|
| 52 | stack = [(convert_path(where), '', package, only_in_packages)] | 
|---|
| 53 | while stack: | 
|---|
| 54 | where, prefix, package, only_in_packages = stack.pop(0) | 
|---|
| 55 | for name in os.listdir(where): | 
|---|
| 56 | fn = os.path.join(where, name) | 
|---|
| 57 | if os.path.isdir(fn): | 
|---|
| 58 | bad_name = False | 
|---|
| 59 | for pattern in exclude_directories: | 
|---|
| 60 | if (fnmatchcase(name, pattern) | 
|---|
| 61 | or fn.lower() == pattern.lower()): | 
|---|
| 62 | bad_name = True | 
|---|
| 63 | if show_ignored: | 
|---|
| 64 | print >> sys.stderr, ( | 
|---|
| 65 | "Directory %s ignored by pattern %s" | 
|---|
| 66 | % (fn, pattern)) | 
|---|
| 67 | break | 
|---|
| 68 | if bad_name: | 
|---|
| 69 | continue | 
|---|
| 70 | if (os.path.isfile(os.path.join(fn, '__init__.py')) | 
|---|
| 71 | and not prefix): | 
|---|
| 72 | if not package: | 
|---|
| 73 | new_package = name | 
|---|
| 74 | else: | 
|---|
| 75 | new_package = package + '.' + name | 
|---|
| 76 | stack.append((fn, '', new_package, False)) | 
|---|
| 77 | else: | 
|---|
| 78 | stack.append((fn, prefix + name + '/', package, only_in_packages)) | 
|---|
| 79 | elif package or not only_in_packages: | 
|---|
| 80 | # is a file | 
|---|
| 81 | bad_name = False | 
|---|
| 82 | for pattern in exclude: | 
|---|
| 83 | if (fnmatchcase(name, pattern) | 
|---|
| 84 | or fn.lower() == pattern.lower()): | 
|---|
| 85 | bad_name = True | 
|---|
| 86 | if show_ignored: | 
|---|
| 87 | print >> sys.stderr, ( | 
|---|
| 88 | "File %s ignored by pattern %s" | 
|---|
| 89 | % (fn, pattern)) | 
|---|
| 90 | break | 
|---|
| 91 | if bad_name: | 
|---|
| 92 | continue | 
|---|
| 93 | out.setdefault(package, []).append(prefix+name) | 
|---|
| 94 | return out | 
|---|
| 95 |  | 
|---|
| 96 | if __name__ == '__main__': | 
|---|
| 97 | import pprint | 
|---|
| 98 | pprint.pprint( | 
|---|
| 99 | find_package_data(show_ignored=True)) | 
|---|