xref: /petsc/src/binding/petsc4py/conf/stubgen.py (revision 6f33641175f69f1db294cc9ba81c3f4ad4f81d49)
155a74a43SLisandro Dalcinimport os
255a74a43SLisandro Dalcinimport inspect
355a74a43SLisandro Dalcinimport textwrap
455a74a43SLisandro Dalcin
555a74a43SLisandro Dalcin
655a74a43SLisandro Dalcindef is_cyfunction(obj):
755a74a43SLisandro Dalcin    return type(obj).__name__ == 'cython_function_or_method'
855a74a43SLisandro Dalcin
955a74a43SLisandro Dalcin
1055a74a43SLisandro Dalcindef is_function(obj):
11*6f336411SStefano Zampini    return inspect.isbuiltin(obj) or is_cyfunction(obj) or type(obj) is type(ord)
1255a74a43SLisandro Dalcin
1355a74a43SLisandro Dalcin
1455a74a43SLisandro Dalcindef is_method(obj):
1555a74a43SLisandro Dalcin    return (
1655a74a43SLisandro Dalcin        inspect.ismethoddescriptor(obj)
1755a74a43SLisandro Dalcin        or inspect.ismethod(obj)
1855a74a43SLisandro Dalcin        or is_cyfunction(obj)
19*6f336411SStefano Zampini        or type(obj)
20*6f336411SStefano Zampini        in (
2155a74a43SLisandro Dalcin            type(str.index),
2255a74a43SLisandro Dalcin            type(str.__add__),
2355a74a43SLisandro Dalcin            type(str.__new__),
2455a74a43SLisandro Dalcin        )
2555a74a43SLisandro Dalcin    )
2655a74a43SLisandro Dalcin
2755a74a43SLisandro Dalcin
2855a74a43SLisandro Dalcindef is_classmethod(obj):
29*6f336411SStefano Zampini    return inspect.isbuiltin(obj) or type(obj).__name__ in (
3055a74a43SLisandro Dalcin        'classmethod',
3155a74a43SLisandro Dalcin        'classmethod_descriptor',
3255a74a43SLisandro Dalcin    )
3355a74a43SLisandro Dalcin
3455a74a43SLisandro Dalcin
3555a74a43SLisandro Dalcindef is_staticmethod(obj):
36*6f336411SStefano Zampini    return type(obj).__name__ in ('staticmethod',)
3755a74a43SLisandro Dalcin
3855a74a43SLisandro Dalcin
3955a74a43SLisandro Dalcindef is_constant(obj):
4055a74a43SLisandro Dalcin    return isinstance(obj, (int, float, str))
4155a74a43SLisandro Dalcin
4255a74a43SLisandro Dalcin
4355a74a43SLisandro Dalcindef is_datadescr(obj):
4455a74a43SLisandro Dalcin    return inspect.isdatadescriptor(obj) and not hasattr(obj, 'fget')
4555a74a43SLisandro Dalcin
4655a74a43SLisandro Dalcin
4755a74a43SLisandro Dalcindef is_property(obj):
4855a74a43SLisandro Dalcin    return inspect.isdatadescriptor(obj) and hasattr(obj, 'fget')
4955a74a43SLisandro Dalcin
5055a74a43SLisandro Dalcin
5155a74a43SLisandro Dalcindef is_class(obj):
5255a74a43SLisandro Dalcin    return inspect.isclass(obj) or type(obj) is type(int)
5355a74a43SLisandro Dalcin
5455a74a43SLisandro Dalcin
5555a74a43SLisandro Dalcinclass Lines(list):
56*6f336411SStefano Zampini    INDENT = ' ' * 4
5755a74a43SLisandro Dalcin    level = 0
5855a74a43SLisandro Dalcin
5955a74a43SLisandro Dalcin    @property
6055a74a43SLisandro Dalcin    def add(self):
6155a74a43SLisandro Dalcin        return self
6255a74a43SLisandro Dalcin
6355a74a43SLisandro Dalcin    @add.setter
6455a74a43SLisandro Dalcin    def add(self, lines):
6555a74a43SLisandro Dalcin        if lines is None:
6655a74a43SLisandro Dalcin            return
6755a74a43SLisandro Dalcin        if isinstance(lines, str):
68*6f336411SStefano Zampini            lines = textwrap.dedent(lines).strip().split('\n')
6955a74a43SLisandro Dalcin        indent = self.INDENT * self.level
7055a74a43SLisandro Dalcin        for line in lines:
7155a74a43SLisandro Dalcin            self.append(indent + line)
7255a74a43SLisandro Dalcin
7355a74a43SLisandro Dalcin
7455a74a43SLisandro Dalcindef signature(obj):
7555a74a43SLisandro Dalcin    doc = obj.__doc__
76*6f336411SStefano Zampini    doc = doc or f'{obj.__name__}: Any'  # FIXME remove line
7755a74a43SLisandro Dalcin    sig = doc.split('\n', 1)[0].split('.', 1)[-1]
7855a74a43SLisandro Dalcin    return sig or None
7955a74a43SLisandro Dalcin
80*6f336411SStefano Zampini
8155a74a43SLisandro Dalcindef visit_constant(constant):
8255a74a43SLisandro Dalcin    name, value = constant
83*6f336411SStefano Zampini    return f'{name}: Final[{type(value).__name__}] = ...'
8455a74a43SLisandro Dalcin
8555a74a43SLisandro Dalcin
8655a74a43SLisandro Dalcindef visit_function(function):
8755a74a43SLisandro Dalcin    sig = signature(function)
88*6f336411SStefano Zampini    return f'def {sig}: ...'
8955a74a43SLisandro Dalcin
9055a74a43SLisandro Dalcin
9155a74a43SLisandro Dalcindef visit_method(method):
9255a74a43SLisandro Dalcin    sig = signature(method)
93*6f336411SStefano Zampini    return f'def {sig}: ...'
9455a74a43SLisandro Dalcin
9555a74a43SLisandro Dalcin
9655a74a43SLisandro Dalcindef visit_datadescr(datadescr):
9755a74a43SLisandro Dalcin    sig = signature(datadescr)
98*6f336411SStefano Zampini    return f'{sig}'
9955a74a43SLisandro Dalcin
10055a74a43SLisandro Dalcin
10155a74a43SLisandro Dalcindef visit_property(prop, name=None):
10255a74a43SLisandro Dalcin    sig = signature(prop.fget)
10355a74a43SLisandro Dalcin    pname = name or prop.fget.__name__
10455a74a43SLisandro Dalcin    ptype = sig.rsplit('->', 1)[-1].strip()
105*6f336411SStefano Zampini    return f'{pname}: {ptype}'
10655a74a43SLisandro Dalcin
10755a74a43SLisandro Dalcin
10855a74a43SLisandro Dalcindef visit_constructor(cls, name='__init__', args=None):
109*6f336411SStefano Zampini    init = name == '__init__'
11055a74a43SLisandro Dalcin    argname = cls.__name__.lower()
11155a74a43SLisandro Dalcin    argtype = cls.__name__
112*6f336411SStefano Zampini    initarg = args or f'{argname}: Optional[{argtype}] = None'
11355a74a43SLisandro Dalcin    selfarg = 'self' if init else 'cls'
11455a74a43SLisandro Dalcin    rettype = 'None' if init else argtype
115*6f336411SStefano Zampini    arglist = f'{selfarg}, {initarg}'
116*6f336411SStefano Zampini    sig = f'{name}({arglist}) -> {rettype}'
117*6f336411SStefano Zampini    return f'def {sig}: ...'
118*6f336411SStefano Zampini
11955a74a43SLisandro Dalcin
12055a74a43SLisandro Dalcindef visit_class(cls, outer=None, done=None):
12155a74a43SLisandro Dalcin    skip = {
12255a74a43SLisandro Dalcin        '__doc__',
12355a74a43SLisandro Dalcin        '__dict__',
12455a74a43SLisandro Dalcin        '__module__',
12555a74a43SLisandro Dalcin        '__weakref__',
12655a74a43SLisandro Dalcin        '__pyx_vtable__',
127baca6076SPierre Jolivet        '__enum2str',  # FIXME refactor implementation
12855a74a43SLisandro Dalcin        '_traceback_',  # FIXME maybe refactor?
12955a74a43SLisandro Dalcin        '__lt__',
13055a74a43SLisandro Dalcin        '__le__',
13155a74a43SLisandro Dalcin        '__ge__',
13255a74a43SLisandro Dalcin        '__gt__',
13355a74a43SLisandro Dalcin    }
13455a74a43SLisandro Dalcin    special = {
135*6f336411SStefano Zampini        '__len__': '__len__(self) -> int',
136*6f336411SStefano Zampini        '__bool__': '__bool__(self) -> bool',
137*6f336411SStefano Zampini        '__hash__': '__hash__(self) -> int',
138*6f336411SStefano Zampini        '__int__': '__int__(self) -> int',
139*6f336411SStefano Zampini        '__index__': '__int__(self) -> int',
140*6f336411SStefano Zampini        '__str__': '__str__(self) -> str',
141*6f336411SStefano Zampini        '__repr__': '__repr__(self) -> str',
142*6f336411SStefano Zampini        '__eq__': '__eq__(self, other: object) -> bool',
143*6f336411SStefano Zampini        '__ne__': '__ne__(self, other: object) -> bool',
14455a74a43SLisandro Dalcin    }
14555a74a43SLisandro Dalcin    constructor = (
14655a74a43SLisandro Dalcin        '__new__',
14755a74a43SLisandro Dalcin        '__init__',
14855a74a43SLisandro Dalcin    )
14955a74a43SLisandro Dalcin
15055a74a43SLisandro Dalcin    qualname = cls.__name__
15155a74a43SLisandro Dalcin    cls_name = cls.__name__
15255a74a43SLisandro Dalcin    if outer is not None and cls_name.startswith(outer):
15355a74a43SLisandro Dalcin        cls_name = cls_name[len(outer) :]
154*6f336411SStefano Zampini        qualname = f'{outer}.{cls_name}'
15555a74a43SLisandro Dalcin
15655a74a43SLisandro Dalcin    override = OVERRIDE.get(qualname, {})
15755a74a43SLisandro Dalcin    done = set() if done is None else done
15855a74a43SLisandro Dalcin    lines = Lines()
15955a74a43SLisandro Dalcin
16055a74a43SLisandro Dalcin    try:
161*6f336411SStefano Zampini
16255a74a43SLisandro Dalcin        class sub(cls):
16355a74a43SLisandro Dalcin            pass
164*6f336411SStefano Zampini
16555a74a43SLisandro Dalcin        final = False
16655a74a43SLisandro Dalcin    except TypeError:
16755a74a43SLisandro Dalcin        final = True
16855a74a43SLisandro Dalcin    if final:
169*6f336411SStefano Zampini        lines.add = '@final'
17055a74a43SLisandro Dalcin    base = cls.__base__
17155a74a43SLisandro Dalcin    if base is object:
172*6f336411SStefano Zampini        lines.add = f'class {cls_name}:'
17355a74a43SLisandro Dalcin    else:
174*6f336411SStefano Zampini        lines.add = f'class {cls_name}({base.__name__}):'
17555a74a43SLisandro Dalcin    lines.level += 1
17655a74a43SLisandro Dalcin    start = len(lines)
17755a74a43SLisandro Dalcin
17855a74a43SLisandro Dalcin    for name in constructor:
17955a74a43SLisandro Dalcin        if name in cls.__dict__:
18055a74a43SLisandro Dalcin            done.add(name)
18155a74a43SLisandro Dalcin
18255a74a43SLisandro Dalcin    if '__hash__' in cls.__dict__:
18355a74a43SLisandro Dalcin        if cls.__hash__ is None:
18455a74a43SLisandro Dalcin            done.add('__hash__')
18555a74a43SLisandro Dalcin
18655a74a43SLisandro Dalcin    dct = cls.__dict__
18755a74a43SLisandro Dalcin    keys = list(dct.keys())
18855a74a43SLisandro Dalcin
18955a74a43SLisandro Dalcin    def dunder(name):
19055a74a43SLisandro Dalcin        return name.startswith('__') and name.endswith('__')
19155a74a43SLisandro Dalcin
19255a74a43SLisandro Dalcin    def members(seq):
19355a74a43SLisandro Dalcin        for name in seq:
19455a74a43SLisandro Dalcin            if name in skip:
19555a74a43SLisandro Dalcin                continue
19655a74a43SLisandro Dalcin            if name in done:
19755a74a43SLisandro Dalcin                continue
19855a74a43SLisandro Dalcin            if dunder(name):
19955a74a43SLisandro Dalcin                if name not in special and name not in override:
20055a74a43SLisandro Dalcin                    done.add(name)
20155a74a43SLisandro Dalcin                    continue
20255a74a43SLisandro Dalcin            yield name
20355a74a43SLisandro Dalcin
20455a74a43SLisandro Dalcin    for name in members(keys):
20555a74a43SLisandro Dalcin        attr = getattr(cls, name)
20655a74a43SLisandro Dalcin        if is_class(attr):
20755a74a43SLisandro Dalcin            done.add(name)
20855a74a43SLisandro Dalcin            lines.add = visit_class(attr, outer=cls_name)
20955a74a43SLisandro Dalcin            continue
21055a74a43SLisandro Dalcin
21155a74a43SLisandro Dalcin    for name in members(keys):
21255a74a43SLisandro Dalcin        if name in override:
21355a74a43SLisandro Dalcin            done.add(name)
21455a74a43SLisandro Dalcin            lines.add = override[name]
21555a74a43SLisandro Dalcin            continue
21655a74a43SLisandro Dalcin
21755a74a43SLisandro Dalcin        if name in special:
21855a74a43SLisandro Dalcin            done.add(name)
21955a74a43SLisandro Dalcin            sig = special[name]
220*6f336411SStefano Zampini            lines.add = f'def {sig}: ...'
22155a74a43SLisandro Dalcin            continue
22255a74a43SLisandro Dalcin
22355a74a43SLisandro Dalcin        attr = getattr(cls, name)
22455a74a43SLisandro Dalcin
22555a74a43SLisandro Dalcin        if is_method(attr):
22655a74a43SLisandro Dalcin            done.add(name)
22755a74a43SLisandro Dalcin            if name == attr.__name__:
22855a74a43SLisandro Dalcin                obj = dct[name]
22955a74a43SLisandro Dalcin                if is_classmethod(obj):
230*6f336411SStefano Zampini                    lines.add = '@classmethod'
23155a74a43SLisandro Dalcin                elif is_staticmethod(obj):
232*6f336411SStefano Zampini                    lines.add = '@staticmethod'
23355a74a43SLisandro Dalcin                lines.add = visit_method(attr)
23455a74a43SLisandro Dalcin            elif True:
235*6f336411SStefano Zampini                lines.add = f'{name} = {attr.__name__}'
23655a74a43SLisandro Dalcin            continue
23755a74a43SLisandro Dalcin
23855a74a43SLisandro Dalcin        if is_datadescr(attr):
23955a74a43SLisandro Dalcin            done.add(name)
24055a74a43SLisandro Dalcin            lines.add = visit_datadescr(attr)
24155a74a43SLisandro Dalcin            continue
24255a74a43SLisandro Dalcin
24355a74a43SLisandro Dalcin        if is_property(attr):
24455a74a43SLisandro Dalcin            done.add(name)
24555a74a43SLisandro Dalcin            lines.add = visit_property(attr, name)
24655a74a43SLisandro Dalcin            continue
24755a74a43SLisandro Dalcin
24855a74a43SLisandro Dalcin        if is_constant(attr):
24955a74a43SLisandro Dalcin            done.add(name)
25055a74a43SLisandro Dalcin            lines.add = visit_constant((name, attr))
25155a74a43SLisandro Dalcin            continue
25255a74a43SLisandro Dalcin
253*6f336411SStefano Zampini    leftovers = [name for name in keys if name not in done and name not in skip]
25455a74a43SLisandro Dalcin    if leftovers:
255*6f336411SStefano Zampini        raise RuntimeError(f'leftovers: {leftovers}')
25655a74a43SLisandro Dalcin
25755a74a43SLisandro Dalcin    if len(lines) == start:
258*6f336411SStefano Zampini        lines.add = 'pass'
25955a74a43SLisandro Dalcin    lines.level -= 1
26055a74a43SLisandro Dalcin    return lines
26155a74a43SLisandro Dalcin
26255a74a43SLisandro Dalcin
26355a74a43SLisandro Dalcindef visit_module(module, done=None):
26455a74a43SLisandro Dalcin    skip = {
26555a74a43SLisandro Dalcin        '__doc__',
26655a74a43SLisandro Dalcin        '__name__',
26755a74a43SLisandro Dalcin        '__loader__',
26855a74a43SLisandro Dalcin        '__spec__',
26955a74a43SLisandro Dalcin        '__file__',
27055a74a43SLisandro Dalcin        '__package__',
27155a74a43SLisandro Dalcin        '__builtins__',
27255a74a43SLisandro Dalcin        '__pyx_unpickle_Enum',  # FIXME review
27355a74a43SLisandro Dalcin    }
27455a74a43SLisandro Dalcin
27555a74a43SLisandro Dalcin    done = set() if done is None else done
27655a74a43SLisandro Dalcin    lines = Lines()
27755a74a43SLisandro Dalcin
27855a74a43SLisandro Dalcin    keys = list(module.__dict__.keys())
279*6f336411SStefano Zampini    keys.sort(key=lambda name: name.startswith('_'))
28055a74a43SLisandro Dalcin
28155a74a43SLisandro Dalcin    constants = [
282*6f336411SStefano Zampini        (name, getattr(module, name))
283*6f336411SStefano Zampini        for name in keys
284*6f336411SStefano Zampini        if all(
285*6f336411SStefano Zampini            (
28655a74a43SLisandro Dalcin                name not in done and name not in skip,
28755a74a43SLisandro Dalcin                isinstance(getattr(module, name), int),
288*6f336411SStefano Zampini            )
289*6f336411SStefano Zampini        )
29055a74a43SLisandro Dalcin    ]
29155a74a43SLisandro Dalcin    for name, value in constants:
29255a74a43SLisandro Dalcin        done.add(name)
29355a74a43SLisandro Dalcin        if name in OVERRIDE:
29455a74a43SLisandro Dalcin            lines.add = OVERRIDE[name]
29555a74a43SLisandro Dalcin        else:
29655a74a43SLisandro Dalcin            lines.add = visit_constant((name, value))
29755a74a43SLisandro Dalcin    if constants:
298*6f336411SStefano Zampini        lines.add = ''
29955a74a43SLisandro Dalcin
30055a74a43SLisandro Dalcin    for name in keys:
30155a74a43SLisandro Dalcin        if name in done or name in skip:
30255a74a43SLisandro Dalcin            continue
30355a74a43SLisandro Dalcin        value = getattr(module, name)
30455a74a43SLisandro Dalcin
30555a74a43SLisandro Dalcin        if is_class(value):
30655a74a43SLisandro Dalcin            done.add(name)
30755a74a43SLisandro Dalcin            if value.__module__ != module.__name__:
30855a74a43SLisandro Dalcin                continue
30955a74a43SLisandro Dalcin            lines.add = visit_class(value)
310*6f336411SStefano Zampini            lines.add = ''
31155a74a43SLisandro Dalcin            instances = [
312*6f336411SStefano Zampini                (k, getattr(module, k))
313*6f336411SStefano Zampini                for k in keys
314*6f336411SStefano Zampini                if all(
315*6f336411SStefano Zampini                    (
31655a74a43SLisandro Dalcin                        k not in done and k not in skip,
31755a74a43SLisandro Dalcin                        type(getattr(module, k)) is value,
318*6f336411SStefano Zampini                    )
319*6f336411SStefano Zampini                )
32055a74a43SLisandro Dalcin            ]
32155a74a43SLisandro Dalcin            for attrname, attrvalue in instances:
32255a74a43SLisandro Dalcin                done.add(attrname)
32355a74a43SLisandro Dalcin                lines.add = visit_constant((attrname, attrvalue))
32455a74a43SLisandro Dalcin            if instances:
325*6f336411SStefano Zampini                lines.add = ''
32655a74a43SLisandro Dalcin            continue
32755a74a43SLisandro Dalcin
32855a74a43SLisandro Dalcin        if is_function(value):
32955a74a43SLisandro Dalcin            done.add(name)
33055a74a43SLisandro Dalcin            if name == value.__name__:
33155a74a43SLisandro Dalcin                lines.add = visit_function(value)
33255a74a43SLisandro Dalcin            else:
333*6f336411SStefano Zampini                lines.add = f'{name} = {value.__name__}'
33455a74a43SLisandro Dalcin            continue
33555a74a43SLisandro Dalcin
336*6f336411SStefano Zampini    lines.add = ''
33755a74a43SLisandro Dalcin    for name in keys:
33855a74a43SLisandro Dalcin        if name in done or name in skip:
33955a74a43SLisandro Dalcin            continue
34055a74a43SLisandro Dalcin        value = getattr(module, name)
34155a74a43SLisandro Dalcin        done.add(name)
34255a74a43SLisandro Dalcin        if name in OVERRIDE:
34355a74a43SLisandro Dalcin            lines.add = OVERRIDE[name]
34455a74a43SLisandro Dalcin        else:
34555a74a43SLisandro Dalcin            lines.add = visit_constant((name, value))
34655a74a43SLisandro Dalcin
347*6f336411SStefano Zampini    leftovers = [name for name in keys if name not in done and name not in skip]
34855a74a43SLisandro Dalcin    if leftovers:
349*6f336411SStefano Zampini        raise RuntimeError(f'leftovers: {leftovers}')
35055a74a43SLisandro Dalcin    return lines
35155a74a43SLisandro Dalcin
35255a74a43SLisandro Dalcin
35355a74a43SLisandro DalcinIMPORTS = """
35455a74a43SLisandro Dalcinfrom __future__ import annotations
35555a74a43SLisandro Dalcinimport sys
35655a74a43SLisandro Dalcinfrom threading import Lock
35755a74a43SLisandro Dalcinfrom typing import (
35855a74a43SLisandro Dalcin    Any,
35955a74a43SLisandro Dalcin    Union,
36055a74a43SLisandro Dalcin    Optional,
36155a74a43SLisandro Dalcin    NoReturn,
36255a74a43SLisandro Dalcin    overload,
36355a74a43SLisandro Dalcin)
36455a74a43SLisandro Dalcinif sys.version_info >= (3, 8):
36555a74a43SLisandro Dalcin    from typing import (
36655a74a43SLisandro Dalcin        final,
36755a74a43SLisandro Dalcin        Final,
36855a74a43SLisandro Dalcin        Literal,
36955a74a43SLisandro Dalcin    )
37055a74a43SLisandro Dalcinelse:
37155a74a43SLisandro Dalcin    from typing_extensions import (
37255a74a43SLisandro Dalcin        final,
37355a74a43SLisandro Dalcin        Final,
37455a74a43SLisandro Dalcin        Literal,
37555a74a43SLisandro Dalcin    )
37655a74a43SLisandro Dalcinif sys.version_info >= (3, 9):
37755a74a43SLisandro Dalcin    from collections.abc import (
37855a74a43SLisandro Dalcin        Callable,
37955a74a43SLisandro Dalcin        Hashable,
38055a74a43SLisandro Dalcin        Iterable,
38155a74a43SLisandro Dalcin        Iterator,
38255a74a43SLisandro Dalcin        Sequence,
38355a74a43SLisandro Dalcin        Mapping,
38455a74a43SLisandro Dalcin    )
38555a74a43SLisandro Dalcinelse:
38655a74a43SLisandro Dalcin    from typing import (
38755a74a43SLisandro Dalcin        Callable,
38855a74a43SLisandro Dalcin        Hashable,
38955a74a43SLisandro Dalcin        Iterable,
39055a74a43SLisandro Dalcin        Iterator,
39155a74a43SLisandro Dalcin        Sequence,
39255a74a43SLisandro Dalcin        Mapping,
39355a74a43SLisandro Dalcin    )
39455a74a43SLisandro Dalcinif sys.version_info >= (3, 11):
39555a74a43SLisandro Dalcin    from typing import Self
39655a74a43SLisandro Dalcinelse:
39755a74a43SLisandro Dalcin    from typing_extensions import Self
39855a74a43SLisandro Dalcinfrom os import PathLike
39955a74a43SLisandro Dalcin
40055a74a43SLisandro Dalcinimport numpy
40155a74a43SLisandro Dalcin
40255a74a43SLisandro DalcinIntType: numpy.dtype = ...
40355a74a43SLisandro DalcinRealType: numpy.dtype = ...
40455a74a43SLisandro DalcinComplexType: numpy.dtype = ...
40555a74a43SLisandro DalcinScalarType: numpy.dtype = ...
40655a74a43SLisandro Dalcin"""
40755a74a43SLisandro Dalcin
40855a74a43SLisandro DalcinOVERRIDE = {
409*6f336411SStefano Zampini    'Error': {},
410*6f336411SStefano Zampini    '__pyx_capi__': '__pyx_capi__: Final[Dict[str, Any]] = ...',
411*6f336411SStefano Zampini    '__type_registry__': '__type_registry__: Final[Dict[int, type[Object]]] = ...',
41255a74a43SLisandro Dalcin}
41355a74a43SLisandro Dalcin
41455a74a43SLisandro DalcinTYPING = """
41555a74a43SLisandro Dalcin"""
41655a74a43SLisandro Dalcin
41755a74a43SLisandro Dalcin
41855a74a43SLisandro Dalcindef visit_petsc4py_PETSc(done=None):
41955a74a43SLisandro Dalcin    from petsc4py import PETSc as module
420*6f336411SStefano Zampini
42155a74a43SLisandro Dalcin    lines = Lines()
42255a74a43SLisandro Dalcin    lines.add = IMPORTS
423*6f336411SStefano Zampini    lines.add = ''
42455a74a43SLisandro Dalcin    lines.add = visit_module(module)
42555a74a43SLisandro Dalcin    lines.add = TYPING
42655a74a43SLisandro Dalcin    return lines
42755a74a43SLisandro Dalcin
42855a74a43SLisandro Dalcin
42955a74a43SLisandro Dalcindef generate(filename):
43055a74a43SLisandro Dalcin    dirname = os.path.dirname(filename)
43155a74a43SLisandro Dalcin    os.makedirs(dirname, exist_ok=True)
43255a74a43SLisandro Dalcin    with open(filename, 'w') as f:
43355a74a43SLisandro Dalcin        for line in visit_petsc4py_PETSc():
43455a74a43SLisandro Dalcin            print(line, file=f)
43555a74a43SLisandro Dalcin
43655a74a43SLisandro Dalcin
43755a74a43SLisandro DalcinOUTDIR = os.path.join('src', 'petsc4py')
43855a74a43SLisandro Dalcin
43955a74a43SLisandro Dalcinif __name__ == '__main__':
44055a74a43SLisandro Dalcin    generate(os.path.join(OUTDIR, 'PETSc.pyi'))
441