--- a/src/modules/flavor/depthlimitedmf.py Wed Apr 29 17:55:57 2015 -0700
+++ b/src/modules/flavor/depthlimitedmf.py Mon May 04 12:33:50 2015 -0700
@@ -27,6 +27,8 @@
import modulefinder
import os
import sys
+if sys.version_info[0] == 3:
+ from importlib.machinery import EXTENSION_SUFFIXES
# A string used as a component of the pkg.depend.runpath value as a special
# token to determine where to insert the runpath that pkgdepend generates itself
@@ -52,17 +54,24 @@
self.name = name
self.builtin = builtin
- self.suffixes = [".py", ".pyc", ".pyo", "/__init__.py", ".so",
- "module.so"]
+ self.patterns = [ "{0}.py", "{0}.pyc", "{0}.pyo", "{0}/__init__.py" ]
+ if sys.version_info[0] == 2:
+ self.patterns += [
+ "{0}.so", "{0}module.so", "64/{0}.so", "64/{0}module.so"
+ ]
+ else:
+ self.patterns += \
+ ["{{0}}{0}".format(s) for s in EXTENSION_SUFFIXES] + \
+ ["64/{{0}}{0}".format(s) for s in EXTENSION_SUFFIXES]
self.dirs = sorted(dirs)
def make_package(self):
"""Declare that this module is a package."""
if self.dirs:
- self.suffixes = ["/__init__.py"]
+ self.patterns = ["{0}/__init__.py"]
else:
- self.suffixes = []
+ self.patterns = []
def get_package_dirs(self):
"""Get the directories where this package might be defined."""
@@ -73,11 +82,11 @@
"""Return all the file names under which this module might be
found."""
- return ["{0}{1}".format(self.name, suf) for suf in self.suffixes]
+ return [ pat.format(self.name) for pat in self.patterns ]
def __str__(self):
return "name:{0} suffixes:{1} dirs:{2}".format(self.name,
- " ".join(self.suffixes), len(self.dirs))
+ " ".join(self.patterns), len(self.dirs))
if __name__ == "__main__":
--- a/src/pkg/manifests/package:pkg.p5m Wed Apr 29 17:55:57 2015 -0700
+++ b/src/pkg/manifests/package:pkg.p5m Mon May 04 12:33:50 2015 -0700
@@ -140,7 +140,9 @@
dir path=$(PYDIRVP)/pkg/flavor
file path=$(PYDIRVP)/pkg/flavor/__init__.py
file path=$(PYDIRVP)/pkg/flavor/base.py
-file path=$(PYDIRVP)/pkg/flavor/depthlimitedmf.py
+# importlib is specific to Python 3 and part of its standard library.
+file path=$(PYDIRVP)/pkg/flavor/depthlimitedmf.py \
+ pkg.depend.bypass-generate=.*importlib.*
file path=$(PYDIRVP)/pkg/flavor/elf.py
file path=$(PYDIRVP)/pkg/flavor/hardlink.py
file path=$(PYDIRVP)/pkg/flavor/python.py
--- a/src/tests/api/t_dependencies.py Wed Apr 29 17:55:57 2015 -0700
+++ b/src/tests/api/t_dependencies.py Mon May 04 12:33:50 2015 -0700
@@ -1375,15 +1375,18 @@
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
- mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo",
- ".so", "module.so"]
+ mod_pats = [
+ "{0}/__init__.py", "{0}.py", "{0}.pyc", "{0}.pyo",
+ "{0}.so", "{0}module.so",
+ "64/{0}.so", "64/{0}module.so"
+ ]
mod_names = ["foobar", "misc_test", "os",
"search_storage", "minidom"]
pkg_names = ["indexer_test", "pkg", "pkg_test", "xml",
"dom"]
expected_deps = set([("python",)] +
[tuple(sorted([
- "{0}{1}".format(n,s) for s in mod_suffs
+ pat.format(n) for pat in mod_pats
]))
for n in mod_names] +
[("{0}/__init__.py".format(n),) for n in pkg_names])
@@ -1426,15 +1429,18 @@
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
- mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo",
- ".so", "module.so"]
+ mod_pats = [
+ "{0}/__init__.py", "{0}.py", "{0}.pyc", "{0}.pyo",
+ "{0}.so", "{0}module.so",
+ "64/{0}.so", "64/{0}module.so"
+ ]
mod_names = ["foobar", "os", "search_storage",
"minidom"]
pkg_names = ["indexer_test", "pkg", "pkg_test", "xml",
"dom"]
expected_deps = set([("python",)] +
[tuple(sorted([
- "{0}{1}".format(n,s) for s in mod_suffs
+ pat.format(n) for pat in mod_pats
]))
for n in mod_names] +
[("{0}/__init__.py".format(n),) for n in pkg_names])
@@ -1481,8 +1487,11 @@
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
- mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo",
- ".so", "module.so"]
+ mod_pats = [
+ "{0}/__init__.py", "{0}.py", "{0}.pyc", "{0}.pyo",
+ "{0}.so", "{0}module.so",
+ "64/{0}.so", "64/{0}module.so"
+ ]
mod_names = ["foobar", "misc_test", "os",
"search_storage", "minidom"]
pkg_names = ["indexer_test", "pkg", "pkg_test",
@@ -1495,7 +1504,7 @@
expected_deps = set([("python",)] +
[tuple(sorted([
- "{0}{1}".format(n,s) for s in mod_suffs
+ pat.format(n) for pat in mod_pats
]))
for n in mod_names] +
[("{0}/__init__.py".format(n),) for n in pkg_names])
@@ -1581,9 +1590,11 @@
pddp = "pkg.debug.depend.path"
pddf = "pkg.debug.depend.file"
- mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo", ".so",
- "module.so"]
- expected_deps = set(["bar{0}".format(s) for s in mod_suffs])
+ mod_pats = [
+ "{0}/__init__.py", "{0}.py", "{0}.pyc", "{0}.pyo",
+ "{0}.so", "{0}module.so", "64/{0}.so", "64/{0}module.so"
+ ]
+ expected_deps = set([pat.format("bar") for pat in mod_pats])
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
@@ -2027,15 +2038,18 @@
def _py_check_all_res(res):
ds, es, ms, pkg_attrs = res
- mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo",
- ".so", "module.so"]
+ mod_pats = [
+ "{0}/__init__.py", "{0}.py", "{0}.pyc", "{0}.pyo",
+ "{0}.so", "{0}module.so",
+ "64/{0}.so", "64/{0}module.so"
+ ]
mod_names = ["foobar", "misc_test", "os",
"search_storage", "minidom"]
pkg_names = ["indexer_test", "pkg", "pkg_test",
"xml", "dom"]
expected_deps = set([("python",)] +
[tuple(sorted([
- "{0}{1}".format(n,s) for s in mod_suffs
+ pat.format(n) for pat in mod_pats
]))
for n in mod_names] +
[("{0}/__init__.py".format(n),) for n in pkg_names])
--- a/src/tests/cli/t_pkgdep.py Wed Apr 29 17:55:57 2015 -0700
+++ b/src/tests/cli/t_pkgdep.py Mon May 04 12:33:50 2015 -0700
@@ -519,6 +519,12 @@
from pkg.misc import EmptyI
"""
+ python3_so_text = """\
+#!/usr/bin/python3.4
+
+import zlib
+"""
+
python_amd_text = """\
#!/usr/bin/amd64/python{0}
@@ -632,6 +638,9 @@
necessary to make the results depend on the sys.path that's
discovered.
"""
+
+ v3 = ver.startswith("3.") and "34m"
+
vp = self.get_ver_paths(ver, proto_area)
self.debug("ver_paths is {0}".format(vp))
pkg_path = self.__make_paths("pkg", vp, reason)
@@ -639,9 +648,17 @@
"{pfx}.file=indexer.py "
"{pfx}.file=indexer.pyc "
"{pfx}.file=indexer.pyo "
+ "{pfx}.file=64/indexer.so "
"{pfx}.file=indexer.so "
- "{pfx}.file=indexer/__init__.py "
- "{pfx}.file=indexermodule.so " +
+ "{pfx}.file=indexer/__init__.py " +
+ (v3 and
+ "{pfx}.file=indexer.abi3.so "
+ "{pfx}.file=indexer.cpython-{v3}.so "
+ "{pfx}.file=64/indexer.abi3.so "
+ "{pfx}.file=64/indexer.cpython-{v3}.so "
+ or
+ "{pfx}.file=indexermodule.so "
+ "{pfx}.file=64/indexermodule.so ") +
pkg_path +
" {pfx}.reason={reason} "
"{pfx}.type=python type=require\n"
@@ -651,8 +668,16 @@
"{pfx}.file=misc.pyc "
"{pfx}.file=misc.pyo "
"{pfx}.file=misc.so "
- "{pfx}.file=misc/__init__.py "
- "{pfx}.file=miscmodule.so " +
+ "{pfx}.file=64/misc.so "
+ "{pfx}.file=misc/__init__.py " +
+ (v3 and
+ "{pfx}.file=misc.abi3.so "
+ "{pfx}.file=misc.cpython-{v3}.so "
+ "{pfx}.file=64/misc.abi3.so "
+ "{pfx}.file=64/misc.cpython-{v3}.so "
+ or
+ "{pfx}.file=64/miscmodule.so "
+ "{pfx}.file=miscmodule.so ") +
pkg_path +
" {pfx}.reason={reason} "
"{pfx}.type=python type=require\n"
@@ -667,9 +692,17 @@
"{pfx}.file=search_storage.py "
"{pfx}.file=search_storage.pyc "
"{pfx}.file=search_storage.pyo "
+ "{pfx}.file=64/search_storage.so "
"{pfx}.file=search_storage.so "
- "{pfx}.file=search_storage/__init__.py "
- "{pfx}.file=search_storagemodule.so " +
+ "{pfx}.file=search_storage/__init__.py " +
+ (v3 and
+ "{pfx}.file=search_storage.abi3.so "
+ "{pfx}.file=search_storage.cpython-{v3}.so "
+ "{pfx}.file=64/search_storage.abi3.so "
+ "{pfx}.file=64/search_storage.cpython-{v3}.so "
+ or
+ "{pfx}.file=64/search_storagemodule.so "
+ "{pfx}.file=search_storagemodule.so ") +
pkg_path +
" {pfx}.reason={reason} "
"{pfx}.type=python type=require\n")
@@ -681,16 +714,24 @@
"{pfx}.file=os.pyc "
"{pfx}.file=os.pyo "
"{pfx}.file=os.so "
- "{pfx}.file=os/__init__.py "
- "{pfx}.file=osmodule.so " +
+ "{pfx}.file=64/os.so "
+ "{pfx}.file=os/__init__.py " +
+ (v3 and
+ "{pfx}.file=os.abi3.so "
+ "{pfx}.file=os.cpython-{v3}.so "
+ "{pfx}.file=64/os.abi3.so "
+ "{pfx}.file=64/os.cpython-{v3}.so "
+ or
+ "{pfx}.file=64/osmodule.so "
+ "{pfx}.file=osmodule.so ") +
self.__make_paths("", vp, reason) +
" {pfx}.reason={reason} "
"{pfx}.type=python type=require\n")
return res.format(
pfx=base.Dependency.DEPEND_DEBUG_PREFIX,
dummy_fmri=base.Dependency.DUMMY_FMRI,
- reason=reason
- )
+ reason=reason, v3=v3
+ )
pyver_other_script_full_manf_1 = """\
file NOHASH group=bin mode=0755 owner=root path={reason} {run_path}
@@ -709,7 +750,7 @@
if ver == py_ver_other:
tmp = self.pyver_other_script_full_manf_1
else:
- raise RuntimeError("Unexcepted version for "
+ raise RuntimeError("Unexpected version for "
"pyver_res_full_manf_1 {0}".format(ver))
return tmp + self.make_pyver_python_res(ver, proto, reason,
include_os=include_os)
@@ -726,8 +767,20 @@
"""Generate the expected results when resolving a manifest which
contains a file with a non-default version of python."""
- suffixes = (".py", ".pyc", ".pyo", ".so", "/__init__.py",
- "module.so")
+ v3 = py_ver_other.startswith("3.") and "34m"
+ patterns = (
+ "{0}.py", "{0}.pyc", "{0}.pyo",
+ "{0}.so", "64/{0}.so",
+ "{0}/__init__.py"
+ )
+ if v3:
+ patterns += (
+ "{0}.abi3.so", "{0}.cpython-{v3}.so",
+ "64/{0}.abi3.so", "64/{0}.cpython-{v3}.so",
+ )
+ else:
+ patterns += ("{0}module.so", "64/{0}module.so")
+
files = ["indexer", "misc", "search_storage"]
# These are the paths to the files which the package depends on.
@@ -757,9 +810,9 @@
return "depend fmri=pkg:/{res_manf} " + \
" ".join(["{pfx}.file=" + rp for rp in rel_paths]) + \
" " + " ".join(["{pfx}.path-id=" + ":".join(sorted([
- proto_str + f + s
+ proto_str + pat.format(f, v3=v3)
for proto_str in vps
- for s in suffixes
+ for pat in patterns
]))
for f in files
]) + " {pfx}.path-id=" + ":".join(sorted(
@@ -768,7 +821,7 @@
"{pfx}.reason=usr/lib/python{py_ver}/" + \
"vendor-packages/pkg/client/indexer.py " + \
"{pfx}.type=script {pfx}.type=python type=require"
-
+
pyver_mismatch_results = """\
depend fmri={dummy_fmri} {pfx}.file=python{default} {pfx}.path=usr/bin {pfx}.reason=usr/lib/python{other}/vendor-packages/pkg/client/indexer.py {pfx}.type=script type=require
""".format(default=py_ver_default, other=py_ver_other, pfx=base.Dependency.DEPEND_DEBUG_PREFIX, dummy_fmri=base.Dependency.DUMMY_FMRI)
@@ -1701,7 +1754,7 @@
# Test that resolve handles multiline actions correctly when
# echoing the manifest. Bug 18740
self.pkgfmt(m1_path)
-
+
self.pkgdepend_resolve(" -vm {0}".format(" ".join([m1_path, m2_path,
m3_path, m4_path, m5_path, m6_path, m7_path, m8_path])))
fh = open(m1_path + ".res")
@@ -2944,6 +2997,41 @@
self.output)
self.check_res("", self.errout)
+ def test_PEP_3149(self):
+ """Test that Python 3 modules importing native modules can find
+ them in the right place, following PEP 3149.
+
+ On Solaris, this means 64-bit only, and with the "m" (pymalloc)
+ flag turned on.
+ """
+
+ # Create a python 3.x file that imports a native module.
+ tp = self.make_manifest(
+ self.pyver_test_manf_1.format(py_ver="3.4"))
+ fp = "usr/lib/python{0}/vendor-packages/pkg/" \
+ "client/indexer.py".format("3.4")
+ self.make_proto_text_file(fp, self.python3_so_text)
+
+ # Run generate
+ self.pkgdepend_generate("-m -d {0} {1}".format(
+ self.test_proto_dir, tp))
+
+ # Take the output, split it into actions, and find exactly one
+ # action which generated a correct dependency on zlib based on
+ # indexer.py.
+ pfx = base.Dependency.DEPEND_DEBUG_PREFIX
+ acts = [
+ a
+ for a in (
+ actions.fromstr(l)
+ for l in self.output.strip().splitlines()
+ )
+ if a.attrs.get(pfx + ".reason") == fp and
+ "64/zlib.cpython-34m.so" in a.attrs[pfx + ".file"]
+ ]
+ self.assert_(len(acts) == 1)
+
+ self.check_res("", self.errout)
if __name__ == "__main__":
unittest.main()