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