File: test_tags.py

package info (click to toggle)
meson-python 0.19.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,328 kB
  • sloc: python: 3,114; ansic: 304; cpp: 16; makefile: 8
file content (143 lines) | stat: -rw-r--r-- 5,637 bytes parent folder | download
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
# SPDX-FileCopyrightText: 2021 The meson-python developers
#
# SPDX-License-Identifier: MIT

import importlib.machinery
import os
import pathlib
import platform
import sys
import sysconfig

from collections import defaultdict
from unittest.mock import Mock

import packaging.tags
import pytest

import mesonpy
import mesonpy._tags

from .conftest import adjust_packaging_platform_tag


# Test against the wheel tag generated by packaging module.
tag = next(packaging.tags.sys_tags())
ABI = tag.abi
INTERPRETER = tag.interpreter
PLATFORM = adjust_packaging_platform_tag(tag.platform)


def get_abi3_suffix():
    for suffix in importlib.machinery.EXTENSION_SUFFIXES:
        if '.abi3' in suffix:  # Unix
            return suffix
        elif suffix == '.pyd':  # Windows
            return suffix


SUFFIX = sysconfig.get_config_var('EXT_SUFFIX')
ABI3SUFFIX = get_abi3_suffix()


def test_wheel_tag():
    assert str(mesonpy._tags.Tag()) == f'{INTERPRETER}-{ABI}-{PLATFORM}'
    assert str(mesonpy._tags.Tag(abi='abi3')) == f'{INTERPRETER}-abi3-{PLATFORM}'


@pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test')
def test_macos_platform_tag(monkeypatch):
    for minor in range(9, 16):
        monkeypatch.setenv('MACOSX_DEPLOYMENT_TARGET', f'10.{minor}')
        version = (10, minor) if platform.mac_ver()[2] != 'arm64' else (11, 0)
        assert next(packaging.tags.mac_platforms(version)) == mesonpy._tags.get_platform_tag()
    for major in range(11, 20):
        for minor in range(3):
            monkeypatch.setenv('MACOSX_DEPLOYMENT_TARGET', f'{major}.{minor}')
            assert next(packaging.tags.mac_platforms((major, minor))) == mesonpy._tags.get_platform_tag()
    for major in range(11, 13):
        monkeypatch.setenv('MACOSX_DEPLOYMENT_TARGET', f'{major}.0')
        assert next(packaging.tags.mac_platforms((major, 0))) == mesonpy._tags.get_platform_tag()
        monkeypatch.setenv('MACOSX_DEPLOYMENT_TARGET', f'{major}')
        assert next(packaging.tags.mac_platforms((major, 0))) == mesonpy._tags.get_platform_tag()


@pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test')
def test_macos_platform_tag_arm64(monkeypatch):
    monkeypatch.setenv('_PYTHON_HOST_PLATFORM', 'macosx-12.0-arm64')
    # Verify that the minimum platform ABI version on arm64 is 11.0.
    monkeypatch.setenv('MACOSX_DEPLOYMENT_TARGET', '10.12')
    assert mesonpy._tags.get_platform_tag() == 'macosx_11_0_arm64'
    monkeypatch.setenv('MACOSX_DEPLOYMENT_TARGET', '12.34')
    assert mesonpy._tags.get_platform_tag() == 'macosx_12_0_arm64'


@pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test')
def test_python_host_platform(monkeypatch):
    monkeypatch.setenv('_PYTHON_HOST_PLATFORM', 'macosx-12.0-arm64')
    assert mesonpy._tags.get_platform_tag().endswith('arm64')
    monkeypatch.setenv('_PYTHON_HOST_PLATFORM', 'macosx-11.1-x86_64')
    assert mesonpy._tags.get_platform_tag().endswith('x86_64')


@pytest.mark.skipif(sys.version_info < (3, 13), reason='requires Python 3.13 or higher')
@pytest.mark.skipif(sys.platform != 'darwin', reason='macOS specific test')
def test_ios_platform_tag(monkeypatch):
    # Mock being on iOS
    monkeypatch.setattr(sys.implementation, '_multiarch', 'arm64-iphoneos')
    monkeypatch.setattr(sysconfig, 'get_platform', Mock(return_value='ios-13.0-arm64-iphoneos'))
    ios_ver = platform.IOSVersionInfo('iOS', '13.0', 'iPhone', False)
    monkeypatch.setattr(platform, 'ios_ver', Mock(return_value=ios_ver))

    # Check the default value
    assert next(packaging.tags.ios_platforms((13, 0))) == mesonpy._tags.get_platform_tag()

    # Check the value when IPHONEOS_DEPLOYMENT_TARGET is set.
    for major in range(13, 20):
        for minor in range(3):
            monkeypatch.setenv('IPHONEOS_DEPLOYMENT_TARGET', f'{major}.{minor}')
            assert next(packaging.tags.ios_platforms((major, minor))) == mesonpy._tags.get_platform_tag()


def wheel_builder_test_factory(content, pure=True, limited_api=False):
    manifest = defaultdict(list)
    manifest.update({key: [(pathlib.Path(x), os.path.join('build', x)) for x in value] for key, value in content.items()})
    return mesonpy._WheelBuilder(None, manifest, limited_api, False)


def test_tag_empty_wheel():
    builder = wheel_builder_test_factory({})
    assert str(builder.tag) == 'py3-none-any'


def test_tag_purelib_wheel():
    builder = wheel_builder_test_factory({
        'purelib': ['pure.py'],
    })
    assert str(builder.tag) == 'py3-none-any'


def test_tag_platlib_wheel():
    builder = wheel_builder_test_factory({
        'platlib': [f'extension{SUFFIX}'],
    })
    assert str(builder.tag) == f'{INTERPRETER}-{ABI}-{PLATFORM}'


def test_tag_stable_abi():
    builder = wheel_builder_test_factory({
        'platlib': [f'extension{ABI3SUFFIX}'],
    }, limited_api=True)
    # PyPy does not support the stable ABI.
    abi = 'abi3' if '__pypy__' not in sys.builtin_module_names else ABI
    assert str(builder.tag) == f'{INTERPRETER}-{abi}-{PLATFORM}'


@pytest.mark.xfail(sys.version_info < (3, 8) and sys.platform == 'win32', reason='Extension modules suffix without ABI tags')
@pytest.mark.xfail('__pypy__' in sys.builtin_module_names, reason='PyPy does not support the stable ABI')
def test_tag_mixed_abi():
    builder = wheel_builder_test_factory({
        'platlib': [f'extension{ABI3SUFFIX}', f'another{SUFFIX}'],
    }, pure=False, limited_api=True)
    with pytest.raises(mesonpy.BuildError, match='The package declares compatibility with Python limited API but '):
        assert str(builder.tag) == f'{INTERPRETER}-abi3-{PLATFORM}'