File: setup.py

package info (click to toggle)
pyerfa 2.0.1.5%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,708 kB
  • sloc: ansic: 13,642; python: 5,786; makefile: 25
file content (209 lines) | stat: -rw-r--r-- 6,811 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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# -*- coding: utf-8 -*-
# Licensed under a 3-clause BSD style license - see LICENSE.rst

import os
import re
import sys
import functools
import setuptools
import subprocess
from warnings import warn
import packaging.version
import sysconfig

try:
    # First available on setuptools 70.1 from January 2024
    # https://setuptools.pypa.io/en/stable/history.html#v70-1-0
    from setuptools.command.bdist_wheel import bdist_wheel
except ImportError:
    from wheel.bdist_wheel import bdist_wheel


LIBERFADIR = os.path.join('liberfa', 'erfa')
ERFA_SRC = os.path.join(LIBERFADIR, 'src')
GEN_FILES = [
    os.path.join('erfa', 'core.py'),
    os.path.join('erfa', 'ufunc.c'),
]


# build with Py_LIMITED_API unless in freethreading build (which does not currently
# support the limited API in py313t)
USE_PY_LIMITED_API = not sysconfig.get_config_var("Py_GIL_DISABLED")

class bdist_wheel_abi3(bdist_wheel):
    def get_tag(self):
        python, abi, plat = super().get_tag()

        if USE_PY_LIMITED_API and python.startswith("cp"):
            # on CPython, our wheels are abi3 and compatible back to 3.9
            return "cp39", "abi3", plat

        return python, abi, plat

def newer(source, target):
    import pathlib

    source = pathlib.Path(source)
    if not source.exists():
        raise FileNotFoundError(f"file '{source.resolve()}' does not exist")

    target = pathlib.Path(target)
    if not target.exists():
        return 1

    return source.stat().st_mtime > target.stat().st_mtime


# https://mail.python.org/pipermail/distutils-sig/2007-September/008253.html
class NumpyExtension(setuptools.Extension):
    """Extension type that adds the NumPy include directory to include_dirs."""

    @property
    def include_dirs(self):
        from numpy import get_include
        return self._include_dirs + [get_include()]

    @include_dirs.setter
    def include_dirs(self, include_dirs):
        self._include_dirs = include_dirs


def get_liberfa_versions(path=os.path.join(LIBERFADIR, 'configure.ac')):
    with open(path) as fd:
        s = fd.read()

    mobj = re.search(r'AC_INIT\(\[erfa\],\[(?P<version>[0-9.]+)\]\)', s)
    if not mobj:
        warn('unable to detect liberfa version')
        return []

    version = packaging.version.parse(mobj.group('version'))

    mobj = re.search(
        r'AC_DEFINE\(\[SOFA_VERSION\], \["(?P<version>\d{8}(_\w)?)"\],', s)
    if not mobj:
        warn('unable to detect SOFA version')
        return []
    sofa_version = mobj.group('version')

    return [
        ('PACKAGE_VERSION', version.base_version),
        ('PACKAGE_VERSION_MAJOR', version.major),
        ('PACKAGE_VERSION_MINOR', version.minor),
        ('PACKAGE_VERSION_MICRO', version.micro),
        ('SOFA_VERSION', sofa_version),
    ]


def get_extensions():
    gen_files_exist = all(os.path.isfile(fn) for fn in GEN_FILES)
    gen_files_outdated = False
    if os.path.isdir(ERFA_SRC):
        # assume that 'erfaversion.c' is updated at each release at least
        src = os.path.join(ERFA_SRC, 'erfaversion.c')
        gen_files_outdated = any(newer(src, fn) for fn in GEN_FILES)
    elif not gen_files_exist:
        raise RuntimeError(
            'Missing "liberfa" source files, unable to generate '
            '"erfa/ufunc.c" and "erfa/core.py". '
            'Please check your source tree. '
            'Maybe "git submodule update" could help.')

    if not gen_files_exist or gen_files_outdated:
        print('Run "erfa_generator.py"')
        cmd = [sys.executable, 'erfa_generator.py', ERFA_SRC, '--quiet']
        subprocess.run(cmd, check=True)

    sources = [os.path.join('erfa', 'ufunc.c')]
    include_dirs = []
    libraries = []
    define_macros = []

    if int(os.environ.get('PYERFA_USE_SYSTEM_LIBERFA', 0)):
        print('Using system liberfa')
        libraries.append('erfa')
    else:
        # get all of the .c files in the liberfa/erfa/src directory
        erfafns = os.listdir(ERFA_SRC)
        sources.extend([os.path.join(ERFA_SRC, fn)
                        for fn in erfafns
                        if fn.endswith('.c') and not fn.startswith('t_')])

        include_dirs.append(ERFA_SRC)

        # liberfa configuration
        config_h = os.path.join(LIBERFADIR, 'config.h')
        if not os.path.exists(config_h):
            print('Configure liberfa')
            configure = os.path.join(LIBERFADIR, 'configure')
            try:
                if not os.path.exists(configure):
                    subprocess.run(
                        ['./bootstrap.sh'], check=True, cwd=LIBERFADIR)
                subprocess.run(['./configure'], check=True, cwd=LIBERFADIR)
            except (subprocess.SubprocessError, OSError) as exc:
                warn(f'unable to configure liberfa: {exc}')

        if not os.path.exists(config_h):
            liberfa_versions = get_liberfa_versions()
            if liberfa_versions:
                print('Configure liberfa ("configure.ac" scan)')
                lines = []
                for name, value in liberfa_versions:
                    # making sure strings are correctly quoted
                    lines.append(f'#define {name} {value!r}'.replace("'", '"'))
                with open(config_h, 'w') as fd:
                    fd.write('\n'.join(lines))
            else:
                warn('unable to get liberfa version')

        if os.path.exists(config_h):
            include_dirs.append(LIBERFADIR)
            define_macros.append(('HAVE_CONFIG_H', '1'))
        elif 'sdist' in sys.argv:
            raise RuntimeError('missing "configure" script in "liberfa/erfa"')

    if USE_PY_LIMITED_API:
        define_macros.append(("Py_LIMITED_API", "0x30900f0"))

    erfa_ext = NumpyExtension(
        name="erfa.ufunc",
        sources=sources,
        include_dirs=include_dirs,
        libraries=libraries,
        define_macros=define_macros,
        py_limited_api=USE_PY_LIMITED_API,
        language="c")

    return [erfa_ext]


try:
    with open('erfa/_dev/scm_version.py') as fd:
        source = fd.read()
except FileNotFoundError:
    guess_next_dev = None
else:
    import types
    scm_version = types.ModuleType('scm_version')
    scm_version.__file__ = 'erfa/_dev/scm_version.py'
    code = compile(source, scm_version.__file__, 'exec')
    try:
        exec(code, scm_version.__dict__)
    except ImportError:
        guess_next_dev = None
    else:
        guess_next_dev = functools.partial(scm_version._guess_next_dev,
                                           liberfadir=LIBERFADIR)

use_scm_version = {
    'write_to': os.path.join('erfa', '_version.py'),
    'version_scheme': guess_next_dev,
}

setuptools.setup(
    use_scm_version=use_scm_version,
    ext_modules=get_extensions(),
    cmdclass={"bdist_wheel": bdist_wheel_abi3},
)