3 from itertools
import product
, starmap
4 import distutils
.command
.install_lib
as orig
7 class install_lib(orig
.install_lib
):
8 """Don't add compiled flags to filenames of non-Python files"""
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
)
17 def get_exclusions(self
):
19 Return a collections.Sized collections.Container of paths to be
20 excluded for single_version_externally_managed installations.
24 for ns_pkg
in self
._get
_SVEM
_NSPs
()
25 for pkg
in self
._all
_packages
(ns_pkg
)
28 excl_specs
= product(all_packages
, self
._gen
_exclusion
_paths
())
29 return set(starmap(self
._exclude
_pkg
_path
, excl_specs
))
31 def _exclude_pkg_path(self
, pkg
, exclusion_path
):
33 Given a package name and exclusion path within that package,
34 compute the full exclusion path.
36 parts
= pkg
.split('.') + [exclusion_path
]
37 return os
.path
.join(self
.install_dir
, *parts
)
40 def _all_packages(pkg_name
):
42 >>> list(install_lib._all_packages('foo.bar.baz'))
43 ['foo.bar.baz', 'foo.bar', 'foo']
47 pkg_name
, sep
, child
= pkg_name
.rpartition('.')
49 def _get_SVEM_NSPs(self
):
51 Get namespace packages (list) but only for
52 single_version_externally_managed installations and empty otherwise.
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
57 if not self
.distribution
.namespace_packages
:
60 install_cmd
= self
.get_finalized_command('install')
61 svem
= install_cmd
.single_version_externally_managed
63 return self
.distribution
.namespace_packages
if svem
else []
66 def _gen_exclusion_paths():
68 Generate file paths to be excluded for namespace packages (bytecode
71 # always exclude the package module itself
77 if not hasattr(sys
, 'implementation'):
80 base
= os
.path
.join('__pycache__', '__init__.' + sys
.implementation
.cache_tag
)
83 yield base
+ '.opt-1.pyc'
84 yield base
+ '.opt-2.pyc'
95 assert preserve_mode
and preserve_times
and not preserve_symlinks
96 exclude
= self
.get_exclusions()
99 return orig
.install_lib
.copy_tree(self
, infile
, outfile
)
101 # Exclude namespace package __init__.py* files from the output
103 from setuptools
.archive_util
import unpack_directory
104 from distutils
import log
110 log
.warn("Skipping installation of %s (namespace package)", dst
)
113 log
.info("copying %s -> %s", src
, os
.path
.dirname(dst
))
117 unpack_directory(infile
, outfile
, pf
)
120 def get_outputs(self
):
121 outputs
= orig
.install_lib
.get_outputs(self
)
122 exclude
= self
.get_exclusions()
124 return [f
for f
in outputs
if f
not in exclude
]