Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

building: fix the references to nested resources in multipackage #5606

Merged
merged 2 commits into from Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 21 additions & 1 deletion PyInstaller/building/api.py
Expand Up @@ -824,8 +824,28 @@ def _set_dependencies(self, analysis, path):
else:
dep_path = self._get_relative_path(path, self._dependencies[tpl[1]])
logger.debug("Referencing %s to be a dependecy for %s, located in %s" % (tpl[1], path, dep_path))
# Determine the path relative to dep_path (i.e, within
# the target directory) from the 'name' component
# of the TOC tuple. If entry is EXTENSION, then the
# relative path needs to be reconstructed from the
# name components.
if tpl[2] == 'EXTENSION':
ext_components = tpl[0].split('.')[:-1]
if ext_components:
rel_path = os.path.join(*ext_components)
else:
rel_path = ''
else:
rel_path = os.path.dirname(tpl[0])
# Take filename from 'path' (second component of
# TOC tuple); this way, we don't need to worry about
# suffix of extensions.
filename = os.path.basename(tpl[1])
# Construct the full file path relative to dep_path...
filename = os.path.join(rel_path, filename)
# ...and use it in new DEPENDENCY entry
analysis.dependencies.append(
(":".join((dep_path, os.path.basename(tpl[1]))),
(":".join((dep_path, filename)),
tpl[1],
"DEPENDENCY"))
toc[i] = (None, None, None)
Expand Down
2 changes: 2 additions & 0 deletions news/5606.bugfix.rst
@@ -0,0 +1,2 @@
Fix ``MERGE()`` to properly set references to nested resources with their
full shared-package-relative path instead of just basename.
@@ -0,0 +1,13 @@
#-----------------------------------------------------------------------------
# Copyright (c) 2021, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------

from PyInstaller.utils.hooks import collect_data_files
datas = collect_data_files('multipackage_test_pkg')
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
@@ -0,0 +1,44 @@
#-----------------------------------------------------------------------------
# Copyright (c) 2021, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------

def _test_basic_imports():
# import a very simple and rarely used pure-python lib ...
import getopt # noqa: F401
# ... and a module importing a shared lib
import ssl # noqa: F401

print('Hello World!')


def _test_nested_data_file():
# try reading secret from a file in sub-directory
import os

secret_file = os.path.join(__path__[0], 'data', 'secret.txt')
print("Reading secret from %s..." % (secret_file))
with open(secret_file, 'r') as fp:
secret = fp.read().strip()
print("Secret: %s" % (secret))

assert secret == 'Secret1234'


def _test_nested_extensions():
# import psutil, which contains an extension in its package directory
import psutil # noqa: F401
print("Successfully imported psutil!")


def test_function():
# Main test function
_test_basic_imports()
_test_nested_data_file()
_test_nested_extensions()
@@ -0,0 +1 @@
Secret1234
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
Expand Up @@ -9,10 +9,5 @@
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------


# import a very simple and rarely used pure-python lib ...
import getopt
# ... and a module importing a shared lib
import ssl

print('Hello World!')
import multipackage_test_pkg
multipackage_test_pkg.test_function()
4 changes: 3 additions & 1 deletion tests/functional/specs/test_multipackage1.spec
Expand Up @@ -19,8 +19,10 @@ __testname__ = 'test_multipackage1'
__testdep__ = 'multipackage1_B'

a = Analysis([os.path.join(SCRIPT_DIR, __testname__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])
b = Analysis([os.path.join(SCRIPT_DIR, __testdep__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])

MERGE((b, __testdep__, __testdep__), (a, __testname__, __testname__))
Expand All @@ -37,7 +39,7 @@ exe = EXE(pyz,
strip=False,
upx=False,
console=1 )

pyzB = PYZ(b.pure)
exeB = EXE(pyzB,
b.scripts,
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/specs/test_multipackage2.spec
Expand Up @@ -20,8 +20,10 @@ __testname__ = 'test_multipackage2'
__testdep__ = 'multipackage2_B'

a = Analysis([os.path.join(SCRIPT_DIR, __testname__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])
b = Analysis([os.path.join(SCRIPT_DIR, __testdep__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])

MERGE((b, __testdep__, os.path.join(__testdep__, __testdep__)),
Expand Down
4 changes: 3 additions & 1 deletion tests/functional/specs/test_multipackage3.spec
Expand Up @@ -20,8 +20,10 @@ __testname__ = 'test_multipackage3'
__testdep__ = 'multipackage3_B'

a = Analysis([os.path.join(SCRIPT_DIR, __testname__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])
b = Analysis([os.path.join(SCRIPT_DIR, __testdep__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])

MERGE((b, __testdep__, os.path.join(__testdep__)),
Expand All @@ -46,7 +48,7 @@ coll = COLLECT( exe,
strip=False,
upx=True,
name=os.path.join('dist', __testname__ ))

pyzB = PYZ(b.pure)
exeB = EXE(pyzB,
b.scripts,
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/specs/test_multipackage4.spec
Expand Up @@ -20,8 +20,10 @@ __testname__ = 'test_multipackage4'
__testdep__ = 'multipackage4_B'

a = Analysis([os.path.join(SCRIPT_DIR, __testname__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])
b = Analysis([os.path.join(SCRIPT_DIR, __testdep__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])

MERGE((b, __testdep__, os.path.join(__testdep__, __testdep__)),
Expand Down
5 changes: 4 additions & 1 deletion tests/functional/specs/test_multipackage5.spec
Expand Up @@ -22,10 +22,13 @@ __testdep__ = 'multipackage5_B'
__testdep2__ = 'multipackage5_C'

a = Analysis([os.path.join(SCRIPT_DIR, __testname__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])
b = Analysis([os.path.join(SCRIPT_DIR, __testdep__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])
c = Analysis([os.path.join(SCRIPT_DIR, __testdep2__ + '.py')],
hookspath=[os.path.join(SPECPATH, SCRIPT_DIR, 'extra-hooks')],
pathex=['.'])


Expand Down Expand Up @@ -72,7 +75,7 @@ coll = COLLECT( exeB,
strip=False,
upx=True,
name=os.path.join('dist', __testdep__))

pyzC = PYZ(c.pure)
exeC = EXE(pyzC,
c.scripts,
Expand Down
3 changes: 3 additions & 0 deletions tests/functional/test_multipackage.py
@@ -1,6 +1,9 @@
import pytest

from PyInstaller.utils.tests import importorskip


@importorskip('psutil') # Used as test for nested extension
@pytest.mark.parametrize(
"spec_file",
(
Expand Down