OLD | NEW |
(Empty) | |
| 1 import os |
| 2 import imp |
| 3 from itertools import product, starmap |
| 4 import distutils.command.install_lib as orig |
| 5 |
| 6 class install_lib(orig.install_lib): |
| 7 """Don't add compiled flags to filenames of non-Python files""" |
| 8 |
| 9 def run(self): |
| 10 self.build() |
| 11 outfiles = self.install() |
| 12 if outfiles is not None: |
| 13 # always compile, in case we have any extension stubs to deal with |
| 14 self.byte_compile(outfiles) |
| 15 |
| 16 def get_exclusions(self): |
| 17 """ |
| 18 Return a collections.Sized collections.Container of paths to be |
| 19 excluded for single_version_externally_managed installations. |
| 20 """ |
| 21 all_packages = ( |
| 22 pkg |
| 23 for ns_pkg in self._get_SVEM_NSPs() |
| 24 for pkg in self._all_packages(ns_pkg) |
| 25 ) |
| 26 |
| 27 excl_specs = product(all_packages, self._gen_exclusion_paths()) |
| 28 return set(starmap(self._exclude_pkg_path, excl_specs)) |
| 29 |
| 30 def _exclude_pkg_path(self, pkg, exclusion_path): |
| 31 """ |
| 32 Given a package name and exclusion path within that package, |
| 33 compute the full exclusion path. |
| 34 """ |
| 35 parts = pkg.split('.') + [exclusion_path] |
| 36 return os.path.join(self.install_dir, *parts) |
| 37 |
| 38 @staticmethod |
| 39 def _all_packages(pkg_name): |
| 40 """ |
| 41 >>> list(install_lib._all_packages('foo.bar.baz')) |
| 42 ['foo.bar.baz', 'foo.bar', 'foo'] |
| 43 """ |
| 44 while pkg_name: |
| 45 yield pkg_name |
| 46 pkg_name, sep, child = pkg_name.rpartition('.') |
| 47 |
| 48 def _get_SVEM_NSPs(self): |
| 49 """ |
| 50 Get namespace packages (list) but only for |
| 51 single_version_externally_managed installations and empty otherwise. |
| 52 """ |
| 53 # TODO: is it necessary to short-circuit here? i.e. what's the cost |
| 54 # if get_finalized_command is called even when namespace_packages is |
| 55 # False? |
| 56 if not self.distribution.namespace_packages: |
| 57 return [] |
| 58 |
| 59 install_cmd = self.get_finalized_command('install') |
| 60 svem = install_cmd.single_version_externally_managed |
| 61 |
| 62 return self.distribution.namespace_packages if svem else [] |
| 63 |
| 64 @staticmethod |
| 65 def _gen_exclusion_paths(): |
| 66 """ |
| 67 Generate file paths to be excluded for namespace packages (bytecode |
| 68 cache files). |
| 69 """ |
| 70 # always exclude the package module itself |
| 71 yield '__init__.py' |
| 72 |
| 73 yield '__init__.pyc' |
| 74 yield '__init__.pyo' |
| 75 |
| 76 if not hasattr(imp, 'get_tag'): |
| 77 return |
| 78 |
| 79 base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) |
| 80 yield base + '.pyc' |
| 81 yield base + '.pyo' |
| 82 |
| 83 def copy_tree( |
| 84 self, infile, outfile, |
| 85 preserve_mode=1, preserve_times=1, preserve_symlinks=0, level=1 |
| 86 ): |
| 87 assert preserve_mode and preserve_times and not preserve_symlinks |
| 88 exclude = self.get_exclusions() |
| 89 |
| 90 if not exclude: |
| 91 return orig.install_lib.copy_tree(self, infile, outfile) |
| 92 |
| 93 # Exclude namespace package __init__.py* files from the output |
| 94 |
| 95 from setuptools.archive_util import unpack_directory |
| 96 from distutils import log |
| 97 |
| 98 outfiles = [] |
| 99 |
| 100 def pf(src, dst): |
| 101 if dst in exclude: |
| 102 log.warn("Skipping installation of %s (namespace package)", |
| 103 dst) |
| 104 return False |
| 105 |
| 106 log.info("copying %s -> %s", src, os.path.dirname(dst)) |
| 107 outfiles.append(dst) |
| 108 return dst |
| 109 |
| 110 unpack_directory(infile, outfile, pf) |
| 111 return outfiles |
| 112 |
| 113 def get_outputs(self): |
| 114 outputs = orig.install_lib.get_outputs(self) |
| 115 exclude = self.get_exclusions() |
| 116 if exclude: |
| 117 return [f for f in outputs if f not in exclude] |
| 118 return outputs |
OLD | NEW |