File: test_regression.py

package info (click to toggle)
pyinstaller 6.18.0%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,824 kB
  • sloc: python: 41,828; ansic: 12,123; makefile: 171; sh: 131; xml: 19
file content (149 lines) | stat: -rw-r--r-- 5,555 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#-----------------------------------------------------------------------------
# Copyright (c) 2005-2023, 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)
#-----------------------------------------------------------------------------

import pathlib
import importlib.machinery

from PyInstaller import compat
from PyInstaller.depend import analysis, bindepend
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.api import PYZ

_MODULES_DIR = pathlib.Path(__file__).parent / "modules"


def test_issue_2492(monkeypatch, tmp_path):
    # Crash if an extension module has an hidden import to ctypes (e.g. added by the hook).

    # Need to set up some values
    monkeypatch.setattr(
        'PyInstaller.config.CONF', {
            'workpath': str(tmp_path),
            'spec': str(tmp_path),
            'warnfile': str(tmp_path / 'warn.txt'),
            'dot-file': str(tmp_path / 'imports.dot'),
            'xref-file': str(tmp_path / 'imports.xref'),
            'hiddenimports': [],
            'specnm': 'issue_2492_script',
            'code_cache': dict(),
        }
    )
    # Speedup: avoid analyzing base_library.zip
    monkeypatch.setattr(analysis, 'PY3_BASE_MODULES', [])

    script = tmp_path / 'script.py'
    script.write_text("import _struct", encoding='utf-8')

    # Create a hook
    (tmp_path / 'hook-_struct.py').write_text("hiddenimports = ['ctypes']", encoding='utf-8')
    Analysis([str(script)], hookspath=[str(tmp_path)], excludes=['encodings', 'pydoc', 'xml', 'distutils'])


def test_issue_5131(monkeypatch, tmp_path):
    """
    While fixing the endless recursion when the package's __init__ module is an extension (see
    tests/unit/test_modulegraph_more.py::package_init_is_extension_*), another error occurred:
    PyInstaller.building._utils._load_code() tried to complete the source code for extension module - triggered by
    PYZ.assemble(), which is collecting all source files - caused by this being marked as "PYMODULE" in the TOC.
    """
    def get_imports(*args, **kwargs):
        # Our faked binary does not match the expected file-format for all platforms, thus the resp. code might crash.
        # Simply ignore this.
        try:
            return orig_get_imports(*args, **kwargs)
        except Exception:
            return []

    orig_get_imports = bindepend.get_imports
    monkeypatch.setattr(bindepend, "get_imports", get_imports)

    # On macOS, we need to similarly override `osxutils.get_macos_sdk_version`.
    if compat.is_darwin:
        from PyInstaller.utils import osx as osxutils

        def get_macos_sdk_version(*args, **kwargs):
            try:
                return orig_get_macos_sdk_version(*args, **kwargs)
            except Exception:
                return (10, 9, 0)  # Minimum version expected by check in Analysis.

        orig_get_macos_sdk_version = osxutils.get_macos_sdk_version
        monkeypatch.setattr(osxutils, "get_macos_sdk_version", get_macos_sdk_version)

    # Set up fake CONF for Analysis
    monkeypatch.setattr(
        'PyInstaller.config.CONF', {
            'workpath': str(tmp_path),
            'spec': str(tmp_path),
            'warnfile': str(tmp_path / 'warn.txt'),
            'dot-file': str(tmp_path / 'imports.dot'),
            'xref-file': str(tmp_path / 'imports.xref'),
            'hiddenimports': [],
            'specnm': 'issue_5131_script',
            'code_cache': dict(),
        }
    )

    # Speedup: avoid analyzing base_library.zip
    monkeypatch.setattr(analysis, 'PY3_BASE_MODULES', [])

    pkg = tmp_path / 'mypkg'
    pkg.mkdir()

    init = pkg / f"__init__{importlib.machinery.EXTENSION_SUFFIXES[0]}"
    init.write_bytes(b'\0\0\0\0\0\0\0\0\0\0\0\0' * 20)

    script = tmp_path / 'script.py'
    script.write_text("import mypkg", encoding='utf-8')

    a = Analysis([str(script)], excludes=['encodings', 'pydoc', 'xml', 'distutils'])
    PYZ(a.pure)


def test_issue_4141(pyi_builder):
    extra_path = _MODULES_DIR / 'pyi_issue_4141'
    pyi_builder.test_script(
        'pyi_issue_4141.py', app_name="main", run_from_path=True, pyi_args=['--path', str(extra_path)]
    )


def test_5734():
    """
    In a regression this will raise a:
        FileNotFoundError: [Errno 2] No such file or directory: b'liblibc.a'
    on some Linux/gcc combinations.
    """
    from PyInstaller.depend.utils import _resolveCtypesImports
    _resolveCtypesImports(["libc"])


def test_5797(pyi_builder):
    """
    Ensure that user overriding os and/or sys (using them as variables) in the global namespace does not affect
    PyInstaller's ctype hooks, installed during bootstrap, which is scenario of the issue #5797.
    """
    pyi_builder.test_source(
        """
        import ctypes

        # Overwrite sys and os in global namespace
        sys = 'watever'
        os = 'something'

        # Use a ctypes.CDLL, which in turn calls _frozen_name() from PyInstaller's ctypes bootstrap hooks.
        try:
            ctypes.CDLL('nonexistent')
        except Exception as e:
            # We expect PyInstallerImportError to be raised
            exception_name = type(e).__name__
            assert exception_name == 'PyInstallerImportError', f"Unexpected exception type: {exception_name}"
        """
    )