File: test_building_utils.py

package info (click to toggle)
pyinstaller 6.18.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 11,824 kB
  • sloc: python: 41,828; ansic: 12,123; makefile: 171; sh: 131; xml: 19
file content (134 lines) | stat: -rw-r--r-- 4,970 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
#-----------------------------------------------------------------------------
# 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 os
import sys
import pathlib

import pytest

from PyInstaller.building import utils


def test_format_binaries_and_datas_not_found_raises_error(tmp_path):
    datas = [('non-existing.txt', '.')]
    (tmp_path / 'existing.txt').touch()  # Create a file with different name, for sanity check.
    # TODO Tighten test when introducing PyInstaller.exceptions
    with pytest.raises(SystemExit):
        utils.format_binaries_and_datas(datas, str(tmp_path))


def test_format_binaries_and_datas_empty_src(tmp_path):
    # `format_binaries_and_datas()` must disallow empty src in `binaries`/`datas` tuples, as those result in implicit
    # collection of the whole current working directory .
    datas = [('', '.')]
    with pytest.raises(SystemExit, match="Empty SRC is not allowed"):
        utils.format_binaries_and_datas(datas, str(tmp_path))


def test_format_binaries_and_datas_basic(tmp_path):
    # (src, dest) tuples to be passed to format_binaries_and_datas()
    DATAS = (
        ('existing.txt', '.'),
        ('other.txt', 'foo'),
        ('*.log', 'logs'),
        ('a/*.log', 'lll'),
        ('a/here.tex', '.'),
        ('b/[abc].tex', 'tex'),
    )

    # Expected entries; they are listed as (src, dest) tuples for readability; the subsequent code transforms them into
    # (dest, src) tuples format used by format_binaries_and_datas().
    EXPECTED = (
        ('existing.txt', 'existing.txt'),
        ('other.txt', 'foo/other.txt'),
        ('aaa.log', 'logs/aaa.log'),
        ('bbb.log', 'logs/bbb.log'),
        ('a/xxx.log', 'lll/xxx.log'),
        ('a/yyy.log', 'lll/yyy.log'),
        ('a/here.tex', 'here.tex'),
        ('b/a.tex', 'tex/a.tex'),
        ('b/b.tex', 'tex/b.tex'),
    )

    # Normalize separator in source paths
    datas = [(os.path.normpath(src), dest) for src, dest in DATAS]

    # Convert the (src, dest) entries from EXPECTED into (dest, src) format, and turn `src` into full path.
    expected = set()
    for src, dest in EXPECTED:
        src_path = tmp_path / src
        dest_path = pathlib.PurePath(dest)  # Normalize separators.
        # Create the file
        src_path.parent.mkdir(parents=True, exist_ok=True)
        src_path.touch()
        # Expected entry
        expected.add((str(dest_path), str(src_path)))

    # Create some additional files that should not be included.
    (tmp_path / 'not.txt').touch()
    (tmp_path / 'a' / 'not.txt').touch()
    (tmp_path / 'b' / 'not.txt').touch()

    res = utils.format_binaries_and_datas(datas, str(tmp_path))
    assert res == expected


def test_format_binaries_and_datas_with_bracket(tmp_path):
    # See issue #2314: the filename contains brackets which are interpreted by glob().
    DATAS = (
        (('b/[abc].tex'), 'tex'),
    )  # yapf: disable

    EXPECTED = (
        ('b/[abc].tex', 'tex/[abc].tex'),
    )  # yapf: disable

    # Normalize separator in source paths
    datas = [(os.path.normpath(src), dest) for src, dest in DATAS]

    # Convert the (src, dest) entries from EXPECTED into (dest, src) format, and turn `src` into full path.
    expected = set()
    for src, dest in EXPECTED:
        src_path = tmp_path / src
        dest_path = pathlib.PurePath(dest)  # Normalize separators.
        # Create the file
        src_path.parent.mkdir(parents=True, exist_ok=True)
        src_path.touch()
        # Expected entry
        expected.add((str(dest_path), str(src_path)))

    # Create some additional files that should not be included.
    (tmp_path / 'tex').mkdir(parents=True, exist_ok=True)
    (tmp_path / 'tex' / 'not.txt').touch()

    res = utils.format_binaries_and_datas(datas, str(tmp_path))
    assert res == expected


def test_should_include_system_binary():
    python_dir = f'python{sys.version_info.major}.{sys.version_info.minor}'
    CASES = [
        (f'{python_dir}/lib-dynload/any', f'/usr/lib64/{python_dir}/lib-dynload/any', [], True),
        ('libany', '/lib64/libpython.so', [], True),
        ('any', '/lib/python/site-packages/any', [], True),
        ('libany', '/etc/libany', [], True),
        ('libany', '/usr/lib/libany', ['*any*'], True),
        ('libany2', '/lib/libany2', ['libnone*', 'libany*'], True),
        ('libnomatch', '/lib/libnomatch', ['libnone*', 'libany*'], False),
    ]

    for case in CASES:
        tuple = (case[0], case[1])
        excepts = case[2]
        expected = case[3]

        assert utils._should_include_system_binary(tuple, excepts) == expected