xref: /petsc/src/binding/petsc4py/conf/stubgen.py (revision 124b60a56262a80503e09b9eaaec281e19388b1e)
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):
116f336411SStefano 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)
196f336411SStefano Zampini        or type(obj)
206f336411SStefano 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):
296f336411SStefano 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):
366f336411SStefano 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):
566f336411SStefano 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):
686f336411SStefano 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__
766f336411SStefano 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
806f336411SStefano Zampini
8155a74a43SLisandro Dalcindef visit_constant(constant):
8255a74a43SLisandro Dalcin    name, value = constant
836f336411SStefano Zampini    return f'{name}: Final[{type(value).__name__}] = ...'
8455a74a43SLisandro Dalcin
8555a74a43SLisandro Dalcin
8655a74a43SLisandro Dalcindef visit_function(function):
8755a74a43SLisandro Dalcin    sig = signature(function)
886f336411SStefano Zampini    return f'def {sig}: ...'
8955a74a43SLisandro Dalcin
9055a74a43SLisandro Dalcin
91*7ec37221Spaul.kuehnerincompatible_overrides = [
92*7ec37221Spaul.kuehner    'DMDA.create',
93*7ec37221Spaul.kuehner    'DMStag.create',
94*7ec37221Spaul.kuehner    'DMSwarm.getField',
95*7ec37221Spaul.kuehner    'DMSwarm.setType',
96*7ec37221Spaul.kuehner    'ViewerHDF5.create',
97*7ec37221Spaul.kuehner    'SF.compose'
98*7ec37221Spaul.kuehner]
99*7ec37221Spaul.kuehnerdef visit_method(method, clas_name=None):
10055a74a43SLisandro Dalcin    sig = signature(method)
101*7ec37221Spaul.kuehner    stub = f'def {sig}: ...'
102*7ec37221Spaul.kuehner    if f'{clas_name}.{method.__name__}' in incompatible_overrides:
103*7ec37221Spaul.kuehner        stub += ' # type: ignore[override]'
104*7ec37221Spaul.kuehner
105*7ec37221Spaul.kuehner    return stub
10655a74a43SLisandro Dalcin
10755a74a43SLisandro Dalcin
10855a74a43SLisandro Dalcindef visit_datadescr(datadescr):
10955a74a43SLisandro Dalcin    sig = signature(datadescr)
1106f336411SStefano Zampini    return f'{sig}'
11155a74a43SLisandro Dalcin
11255a74a43SLisandro Dalcin
11355a74a43SLisandro Dalcindef visit_property(prop, name=None):
11455a74a43SLisandro Dalcin    sig = signature(prop.fget)
11555a74a43SLisandro Dalcin    pname = name or prop.fget.__name__
11655a74a43SLisandro Dalcin    ptype = sig.rsplit('->', 1)[-1].strip()
1176f336411SStefano Zampini    return f'{pname}: {ptype}'
11855a74a43SLisandro Dalcin
11955a74a43SLisandro Dalcin
12055a74a43SLisandro Dalcindef visit_constructor(cls, name='__init__', args=None):
1216f336411SStefano Zampini    init = name == '__init__'
12255a74a43SLisandro Dalcin    argname = cls.__name__.lower()
12355a74a43SLisandro Dalcin    argtype = cls.__name__
1246f336411SStefano Zampini    initarg = args or f'{argname}: Optional[{argtype}] = None'
12555a74a43SLisandro Dalcin    selfarg = 'self' if init else 'cls'
12655a74a43SLisandro Dalcin    rettype = 'None' if init else argtype
1276f336411SStefano Zampini    arglist = f'{selfarg}, {initarg}'
1286f336411SStefano Zampini    sig = f'{name}({arglist}) -> {rettype}'
1296f336411SStefano Zampini    return f'def {sig}: ...'
1306f336411SStefano Zampini
13155a74a43SLisandro Dalcin
132*7ec37221Spaul.kuehnervisited_classes = set()
133*7ec37221Spaul.kuehner
134*7ec37221Spaul.kuehner
13555a74a43SLisandro Dalcindef visit_class(cls, outer=None, done=None):
13655a74a43SLisandro Dalcin    skip = {
13755a74a43SLisandro Dalcin        '__doc__',
13855a74a43SLisandro Dalcin        '__dict__',
13955a74a43SLisandro Dalcin        '__module__',
14055a74a43SLisandro Dalcin        '__weakref__',
14155a74a43SLisandro Dalcin        '__pyx_vtable__',
142baca6076SPierre Jolivet        '__enum2str',  # FIXME refactor implementation
14355a74a43SLisandro Dalcin        '_traceback_',  # FIXME maybe refactor?
14455a74a43SLisandro Dalcin        '__lt__',
14555a74a43SLisandro Dalcin        '__le__',
14655a74a43SLisandro Dalcin        '__ge__',
14755a74a43SLisandro Dalcin        '__gt__',
14855a74a43SLisandro Dalcin    }
14955a74a43SLisandro Dalcin    special = {
1506f336411SStefano Zampini        '__len__': '__len__(self) -> int',
1516f336411SStefano Zampini        '__bool__': '__bool__(self) -> bool',
1526f336411SStefano Zampini        '__hash__': '__hash__(self) -> int',
1536f336411SStefano Zampini        '__int__': '__int__(self) -> int',
1546f336411SStefano Zampini        '__index__': '__int__(self) -> int',
1556f336411SStefano Zampini        '__str__': '__str__(self) -> str',
1566f336411SStefano Zampini        '__repr__': '__repr__(self) -> str',
1576f336411SStefano Zampini        '__eq__': '__eq__(self, other: object) -> bool',
1586f336411SStefano Zampini        '__ne__': '__ne__(self, other: object) -> bool',
15955a74a43SLisandro Dalcin    }
16055a74a43SLisandro Dalcin    constructor = (
16155a74a43SLisandro Dalcin        '__new__',
16255a74a43SLisandro Dalcin        '__init__',
16355a74a43SLisandro Dalcin    )
16455a74a43SLisandro Dalcin
16555a74a43SLisandro Dalcin    qualname = cls.__name__
16655a74a43SLisandro Dalcin    cls_name = cls.__name__
16755a74a43SLisandro Dalcin    if outer is not None and cls_name.startswith(outer):
16855a74a43SLisandro Dalcin        cls_name = cls_name[len(outer) :]
1696f336411SStefano Zampini        qualname = f'{outer}.{cls_name}'
17055a74a43SLisandro Dalcin
171*7ec37221Spaul.kuehner    if qualname in visited_classes:
172*7ec37221Spaul.kuehner        return ''
173*7ec37221Spaul.kuehner
174*7ec37221Spaul.kuehner    visited_classes.add(qualname)
175*7ec37221Spaul.kuehner
17655a74a43SLisandro Dalcin    override = OVERRIDE.get(qualname, {})
17755a74a43SLisandro Dalcin    done = set() if done is None else done
17855a74a43SLisandro Dalcin    lines = Lines()
17955a74a43SLisandro Dalcin
18055a74a43SLisandro Dalcin    try:
1816f336411SStefano Zampini
18255a74a43SLisandro Dalcin        class sub(cls):
18355a74a43SLisandro Dalcin            pass
1846f336411SStefano Zampini
18555a74a43SLisandro Dalcin        final = False
18655a74a43SLisandro Dalcin    except TypeError:
18755a74a43SLisandro Dalcin        final = True
18855a74a43SLisandro Dalcin    if final:
1896f336411SStefano Zampini        lines.add = '@final'
19055a74a43SLisandro Dalcin    base = cls.__base__
19155a74a43SLisandro Dalcin    if base is object:
1926f336411SStefano Zampini        lines.add = f'class {cls_name}:'
19355a74a43SLisandro Dalcin    else:
1946f336411SStefano Zampini        lines.add = f'class {cls_name}({base.__name__}):'
19555a74a43SLisandro Dalcin    lines.level += 1
19655a74a43SLisandro Dalcin    start = len(lines)
19755a74a43SLisandro Dalcin
19855a74a43SLisandro Dalcin    for name in constructor:
199*7ec37221Spaul.kuehner        if name in override:
200*7ec37221Spaul.kuehner            continue
20155a74a43SLisandro Dalcin        if name in cls.__dict__:
20255a74a43SLisandro Dalcin            done.add(name)
20355a74a43SLisandro Dalcin
20455a74a43SLisandro Dalcin    if '__hash__' in cls.__dict__:
20555a74a43SLisandro Dalcin        if cls.__hash__ is None:
20655a74a43SLisandro Dalcin            done.add('__hash__')
20755a74a43SLisandro Dalcin
20855a74a43SLisandro Dalcin    dct = cls.__dict__
20955a74a43SLisandro Dalcin    keys = list(dct.keys())
21055a74a43SLisandro Dalcin
21155a74a43SLisandro Dalcin    def dunder(name):
21255a74a43SLisandro Dalcin        return name.startswith('__') and name.endswith('__')
21355a74a43SLisandro Dalcin
21455a74a43SLisandro Dalcin    def members(seq):
21555a74a43SLisandro Dalcin        for name in seq:
21655a74a43SLisandro Dalcin            if name in skip:
21755a74a43SLisandro Dalcin                continue
21855a74a43SLisandro Dalcin            if name in done:
21955a74a43SLisandro Dalcin                continue
22055a74a43SLisandro Dalcin            if dunder(name):
22155a74a43SLisandro Dalcin                if name not in special and name not in override:
22255a74a43SLisandro Dalcin                    done.add(name)
22355a74a43SLisandro Dalcin                    continue
22455a74a43SLisandro Dalcin            yield name
22555a74a43SLisandro Dalcin
22655a74a43SLisandro Dalcin    for name in members(keys):
22755a74a43SLisandro Dalcin        attr = getattr(cls, name)
22855a74a43SLisandro Dalcin        if is_class(attr):
22955a74a43SLisandro Dalcin            done.add(name)
23055a74a43SLisandro Dalcin            lines.add = visit_class(attr, outer=cls_name)
23155a74a43SLisandro Dalcin            continue
23255a74a43SLisandro Dalcin
23355a74a43SLisandro Dalcin    for name in members(keys):
23455a74a43SLisandro Dalcin        if name in override:
23555a74a43SLisandro Dalcin            done.add(name)
23655a74a43SLisandro Dalcin            lines.add = override[name]
23755a74a43SLisandro Dalcin            continue
23855a74a43SLisandro Dalcin
23955a74a43SLisandro Dalcin        if name in special:
24055a74a43SLisandro Dalcin            done.add(name)
24155a74a43SLisandro Dalcin            sig = special[name]
2426f336411SStefano Zampini            lines.add = f'def {sig}: ...'
24355a74a43SLisandro Dalcin            continue
24455a74a43SLisandro Dalcin
24555a74a43SLisandro Dalcin        attr = getattr(cls, name)
24655a74a43SLisandro Dalcin
24755a74a43SLisandro Dalcin        if is_method(attr):
24855a74a43SLisandro Dalcin            done.add(name)
24955a74a43SLisandro Dalcin            if name == attr.__name__:
25055a74a43SLisandro Dalcin                obj = dct[name]
25155a74a43SLisandro Dalcin                if is_classmethod(obj):
2526f336411SStefano Zampini                    lines.add = '@classmethod'
25355a74a43SLisandro Dalcin                elif is_staticmethod(obj):
2546f336411SStefano Zampini                    lines.add = '@staticmethod'
255*7ec37221Spaul.kuehner                lines.add = visit_method(attr, qualname)
25655a74a43SLisandro Dalcin            elif True:
2576f336411SStefano Zampini                lines.add = f'{name} = {attr.__name__}'
25855a74a43SLisandro Dalcin            continue
25955a74a43SLisandro Dalcin
26055a74a43SLisandro Dalcin        if is_datadescr(attr):
26155a74a43SLisandro Dalcin            done.add(name)
26255a74a43SLisandro Dalcin            lines.add = visit_datadescr(attr)
26355a74a43SLisandro Dalcin            continue
26455a74a43SLisandro Dalcin
26555a74a43SLisandro Dalcin        if is_property(attr):
26655a74a43SLisandro Dalcin            done.add(name)
26755a74a43SLisandro Dalcin            lines.add = visit_property(attr, name)
26855a74a43SLisandro Dalcin            continue
26955a74a43SLisandro Dalcin
27055a74a43SLisandro Dalcin        if is_constant(attr):
27155a74a43SLisandro Dalcin            done.add(name)
27255a74a43SLisandro Dalcin            lines.add = visit_constant((name, attr))
27355a74a43SLisandro Dalcin            continue
27455a74a43SLisandro Dalcin
2756f336411SStefano Zampini    leftovers = [name for name in keys if name not in done and name not in skip]
27655a74a43SLisandro Dalcin    if leftovers:
2776f336411SStefano Zampini        raise RuntimeError(f'leftovers: {leftovers}')
27855a74a43SLisandro Dalcin
27955a74a43SLisandro Dalcin    if len(lines) == start:
280*7ec37221Spaul.kuehner        lines.add = '...'
28155a74a43SLisandro Dalcin    lines.level -= 1
28255a74a43SLisandro Dalcin    return lines
28355a74a43SLisandro Dalcin
28455a74a43SLisandro Dalcin
28555a74a43SLisandro Dalcindef visit_module(module, done=None):
28655a74a43SLisandro Dalcin    skip = {
28755a74a43SLisandro Dalcin        '__doc__',
28855a74a43SLisandro Dalcin        '__name__',
28955a74a43SLisandro Dalcin        '__loader__',
29055a74a43SLisandro Dalcin        '__spec__',
29155a74a43SLisandro Dalcin        '__file__',
29255a74a43SLisandro Dalcin        '__package__',
29355a74a43SLisandro Dalcin        '__builtins__',
29455a74a43SLisandro Dalcin        '__pyx_unpickle_Enum',  # FIXME review
29555a74a43SLisandro Dalcin    }
29655a74a43SLisandro Dalcin
29755a74a43SLisandro Dalcin    done = set() if done is None else done
29855a74a43SLisandro Dalcin    lines = Lines()
29955a74a43SLisandro Dalcin
30055a74a43SLisandro Dalcin    keys = list(module.__dict__.keys())
3016f336411SStefano Zampini    keys.sort(key=lambda name: name.startswith('_'))
30255a74a43SLisandro Dalcin
30355a74a43SLisandro Dalcin    constants = [
3046f336411SStefano Zampini        (name, getattr(module, name))
3056f336411SStefano Zampini        for name in keys
3066f336411SStefano Zampini        if all(
3076f336411SStefano Zampini            (
30855a74a43SLisandro Dalcin                name not in done and name not in skip,
30955a74a43SLisandro Dalcin                isinstance(getattr(module, name), int),
3106f336411SStefano Zampini            )
3116f336411SStefano Zampini        )
31255a74a43SLisandro Dalcin    ]
31355a74a43SLisandro Dalcin    for name, value in constants:
31455a74a43SLisandro Dalcin        done.add(name)
31555a74a43SLisandro Dalcin        if name in OVERRIDE:
31655a74a43SLisandro Dalcin            lines.add = OVERRIDE[name]
31755a74a43SLisandro Dalcin        else:
31855a74a43SLisandro Dalcin            lines.add = visit_constant((name, value))
31955a74a43SLisandro Dalcin    if constants:
3206f336411SStefano Zampini        lines.add = ''
32155a74a43SLisandro Dalcin
32255a74a43SLisandro Dalcin    for name in keys:
32355a74a43SLisandro Dalcin        if name in done or name in skip:
32455a74a43SLisandro Dalcin            continue
32555a74a43SLisandro Dalcin        value = getattr(module, name)
32655a74a43SLisandro Dalcin
32755a74a43SLisandro Dalcin        if is_class(value):
32855a74a43SLisandro Dalcin            done.add(name)
32955a74a43SLisandro Dalcin            if value.__module__ != module.__name__:
33055a74a43SLisandro Dalcin                continue
33155a74a43SLisandro Dalcin            lines.add = visit_class(value)
3326f336411SStefano Zampini            lines.add = ''
33355a74a43SLisandro Dalcin            instances = [
3346f336411SStefano Zampini                (k, getattr(module, k))
3356f336411SStefano Zampini                for k in keys
3366f336411SStefano Zampini                if all(
3376f336411SStefano Zampini                    (
33855a74a43SLisandro Dalcin                        k not in done and k not in skip,
33955a74a43SLisandro Dalcin                        type(getattr(module, k)) is value,
3406f336411SStefano Zampini                    )
3416f336411SStefano Zampini                )
34255a74a43SLisandro Dalcin            ]
34355a74a43SLisandro Dalcin            for attrname, attrvalue in instances:
34455a74a43SLisandro Dalcin                done.add(attrname)
34555a74a43SLisandro Dalcin                lines.add = visit_constant((attrname, attrvalue))
34655a74a43SLisandro Dalcin            if instances:
3476f336411SStefano Zampini                lines.add = ''
34855a74a43SLisandro Dalcin            continue
34955a74a43SLisandro Dalcin
35055a74a43SLisandro Dalcin        if is_function(value):
35155a74a43SLisandro Dalcin            done.add(name)
35255a74a43SLisandro Dalcin            if name == value.__name__:
35355a74a43SLisandro Dalcin                lines.add = visit_function(value)
35455a74a43SLisandro Dalcin            else:
3556f336411SStefano Zampini                lines.add = f'{name} = {value.__name__}'
35655a74a43SLisandro Dalcin            continue
35755a74a43SLisandro Dalcin
3586f336411SStefano Zampini    lines.add = ''
35955a74a43SLisandro Dalcin    for name in keys:
36055a74a43SLisandro Dalcin        if name in done or name in skip:
36155a74a43SLisandro Dalcin            continue
36255a74a43SLisandro Dalcin        value = getattr(module, name)
36355a74a43SLisandro Dalcin        done.add(name)
36455a74a43SLisandro Dalcin        if name in OVERRIDE:
36555a74a43SLisandro Dalcin            lines.add = OVERRIDE[name]
36655a74a43SLisandro Dalcin        else:
36755a74a43SLisandro Dalcin            lines.add = visit_constant((name, value))
36855a74a43SLisandro Dalcin
3696f336411SStefano Zampini    leftovers = [name for name in keys if name not in done and name not in skip]
37055a74a43SLisandro Dalcin    if leftovers:
3716f336411SStefano Zampini        raise RuntimeError(f'leftovers: {leftovers}')
37255a74a43SLisandro Dalcin    return lines
37355a74a43SLisandro Dalcin
37455a74a43SLisandro Dalcin
37555a74a43SLisandro DalcinIMPORTS = """
37655a74a43SLisandro Dalcinfrom __future__ import annotations
37755a74a43SLisandro Dalcinimport sys
37855a74a43SLisandro Dalcinfrom threading import Lock
37955a74a43SLisandro Dalcinfrom typing import (
38055a74a43SLisandro Dalcin    Any,
38155a74a43SLisandro Dalcin    Union,
38255a74a43SLisandro Dalcin    Optional,
38355a74a43SLisandro Dalcin    NoReturn,
38455a74a43SLisandro Dalcin    overload,
38555a74a43SLisandro Dalcin)
38655a74a43SLisandro Dalcinif sys.version_info >= (3, 8):
38755a74a43SLisandro Dalcin    from typing import (
38855a74a43SLisandro Dalcin        final,
38955a74a43SLisandro Dalcin        Final,
39055a74a43SLisandro Dalcin        Literal,
39155a74a43SLisandro Dalcin    )
39255a74a43SLisandro Dalcinelse:
39355a74a43SLisandro Dalcin    from typing_extensions import (
39455a74a43SLisandro Dalcin        final,
39555a74a43SLisandro Dalcin        Final,
39655a74a43SLisandro Dalcin        Literal,
39755a74a43SLisandro Dalcin    )
39855a74a43SLisandro Dalcinif sys.version_info >= (3, 9):
39955a74a43SLisandro Dalcin    from collections.abc import (
40055a74a43SLisandro Dalcin        Callable,
40155a74a43SLisandro Dalcin        Hashable,
40255a74a43SLisandro Dalcin        Iterable,
40355a74a43SLisandro Dalcin        Iterator,
40455a74a43SLisandro Dalcin        Sequence,
40555a74a43SLisandro Dalcin        Mapping,
40655a74a43SLisandro Dalcin    )
40755a74a43SLisandro Dalcinelse:
40855a74a43SLisandro Dalcin    from typing import (
40955a74a43SLisandro Dalcin        Callable,
41055a74a43SLisandro Dalcin        Hashable,
41155a74a43SLisandro Dalcin        Iterable,
41255a74a43SLisandro Dalcin        Iterator,
41355a74a43SLisandro Dalcin        Sequence,
41455a74a43SLisandro Dalcin        Mapping,
41555a74a43SLisandro Dalcin    )
41655a74a43SLisandro Dalcinif sys.version_info >= (3, 11):
41755a74a43SLisandro Dalcin    from typing import Self
41855a74a43SLisandro Dalcinelse:
41955a74a43SLisandro Dalcin    from typing_extensions import Self
42055a74a43SLisandro Dalcinfrom os import PathLike
42155a74a43SLisandro Dalcin
42255a74a43SLisandro Dalcinimport numpy
42355a74a43SLisandro Dalcin
424*7ec37221Spaul.kuehnerfrom numpy import (
425*7ec37221Spaul.kuehner    dtype,
426*7ec37221Spaul.kuehner    ndarray,
427*7ec37221Spaul.kuehner)
428*7ec37221Spaul.kuehner
429*7ec37221Spaul.kuehnerfrom mpi4py.MPI import (
430*7ec37221Spaul.kuehner    Datatype,
431*7ec37221Spaul.kuehner    Intracomm,
432*7ec37221Spaul.kuehner    Op,
433*7ec37221Spaul.kuehner)
434*7ec37221Spaul.kuehner
435*7ec37221Spaul.kuehnerfrom petsc4py.typing import (
436*7ec37221Spaul.kuehner    Scalar,
437*7ec37221Spaul.kuehner    ArrayBool,
438*7ec37221Spaul.kuehner    ArrayComplex,
439*7ec37221Spaul.kuehner    ArrayInt,
440*7ec37221Spaul.kuehner    ArrayReal,
441*7ec37221Spaul.kuehner    ArrayScalar,
442*7ec37221Spaul.kuehner    CSRIndicesSpec,
443*7ec37221Spaul.kuehner    CSRSpec,
444*7ec37221Spaul.kuehner    DMCoarsenHookFunction,
445*7ec37221Spaul.kuehner    DMRestrictHookFunction,
446*7ec37221Spaul.kuehner    DimsSpec,
447*7ec37221Spaul.kuehner    KSPConvergenceTestFunction,
448*7ec37221Spaul.kuehner    KSPMonitorFunction,
449*7ec37221Spaul.kuehner    KSPOperatorsFunction,
450*7ec37221Spaul.kuehner    KSPPostSolveFunction,
451*7ec37221Spaul.kuehner    KSPPreSolveFunction,
452*7ec37221Spaul.kuehner    KSPRHSFunction,
453*7ec37221Spaul.kuehner    LayoutSizeSpec,
454*7ec37221Spaul.kuehner    MatAssemblySpec,
455*7ec37221Spaul.kuehner    MatBlockSizeSpec,
456*7ec37221Spaul.kuehner    MatNullFunction,
457*7ec37221Spaul.kuehner    MatSizeSpec,
458*7ec37221Spaul.kuehner    NNZSpec,
459*7ec37221Spaul.kuehner    NormTypeSpec,
460*7ec37221Spaul.kuehner    PetscOptionsHandlerFunction,
461*7ec37221Spaul.kuehner    ScatterModeSpec,
462*7ec37221Spaul.kuehner    SNESMonitorFunction,
463*7ec37221Spaul.kuehner    SNESObjFunction,
464*7ec37221Spaul.kuehner    SNESFunction,
465*7ec37221Spaul.kuehner    SNESJacobianFunction,
466*7ec37221Spaul.kuehner    SNESGuessFunction,
467*7ec37221Spaul.kuehner    SNESUpdateFunction,
468*7ec37221Spaul.kuehner    SNESLSPreFunction,
469*7ec37221Spaul.kuehner    SNESNGSFunction,
470*7ec37221Spaul.kuehner    SNESConvergedFunction,
471*7ec37221Spaul.kuehner    TAOConstraintsFunction,
472*7ec37221Spaul.kuehner    TAOConstraintsJacobianFunction,
473*7ec37221Spaul.kuehner    TAOConvergedFunction,
474*7ec37221Spaul.kuehner    TAOGradientFunction,
475*7ec37221Spaul.kuehner    TAOHessianFunction,
476*7ec37221Spaul.kuehner    TAOJacobianFunction,
477*7ec37221Spaul.kuehner    TAOJacobianResidualFunction,
478*7ec37221Spaul.kuehner    TAOMonitorFunction,
479*7ec37221Spaul.kuehner    TAOObjectiveFunction,
480*7ec37221Spaul.kuehner    TAOObjectiveGradientFunction,
481*7ec37221Spaul.kuehner    TAOResidualFunction,
482*7ec37221Spaul.kuehner    TAOUpdateFunction,
483*7ec37221Spaul.kuehner    TAOVariableBoundsFunction,
484*7ec37221Spaul.kuehner    TAOLSGradientFunction,
485*7ec37221Spaul.kuehner    TAOLSObjectiveFunction,
486*7ec37221Spaul.kuehner    TAOLSObjectiveGradientFunction,
487*7ec37221Spaul.kuehner    TSI2Function,
488*7ec37221Spaul.kuehner    TSI2Jacobian,
489*7ec37221Spaul.kuehner    TSI2JacobianP,
490*7ec37221Spaul.kuehner    TSIFunction,
491*7ec37221Spaul.kuehner    TSIJacobian,
492*7ec37221Spaul.kuehner    TSIJacobianP,
493*7ec37221Spaul.kuehner    TSIndicatorFunction,
494*7ec37221Spaul.kuehner    TSMonitorFunction,
495*7ec37221Spaul.kuehner    TSPostEventFunction,
496*7ec37221Spaul.kuehner    TSPostStepFunction,
497*7ec37221Spaul.kuehner    TSPreStepFunction,
498*7ec37221Spaul.kuehner    TSRHSFunction,
499*7ec37221Spaul.kuehner    TSRHSJacobian,
500*7ec37221Spaul.kuehner    TSRHSJacobianP,
501*7ec37221Spaul.kuehner    AccessModeSpec,
502*7ec37221Spaul.kuehner    InsertModeSpec,
503*7ec37221Spaul.kuehner)
504*7ec37221Spaul.kuehner
50555a74a43SLisandro DalcinIntType: numpy.dtype = ...
50655a74a43SLisandro DalcinRealType: numpy.dtype = ...
50755a74a43SLisandro DalcinComplexType: numpy.dtype = ...
50855a74a43SLisandro DalcinScalarType: numpy.dtype = ...
50955a74a43SLisandro Dalcin"""
51055a74a43SLisandro Dalcin
51155a74a43SLisandro DalcinOVERRIDE = {
512*7ec37221Spaul.kuehner    'Error': {
513*7ec37221Spaul.kuehner        '__init__': 'def __init__(self, ierr: int = 0) -> None: ...',
514*7ec37221Spaul.kuehner    },
515*7ec37221Spaul.kuehner    'Options': {
516*7ec37221Spaul.kuehner        '__init__': 'def __init__(self, prefix: str | None = None) -> None: ...',
517*7ec37221Spaul.kuehner    },
518*7ec37221Spaul.kuehner    '__pyx_capi__': '__pyx_capi__: Final[dict[str, Any]] = ...',
519*7ec37221Spaul.kuehner    '__type_registry__': '__type_registry__: Final[dict[int, type[Object]]] = ...',
52055a74a43SLisandro Dalcin}
52155a74a43SLisandro Dalcin
52255a74a43SLisandro DalcinTYPING = """
52355a74a43SLisandro Dalcin"""
52455a74a43SLisandro Dalcin
52555a74a43SLisandro Dalcin
52655a74a43SLisandro Dalcindef visit_petsc4py_PETSc(done=None):
52755a74a43SLisandro Dalcin    from petsc4py import PETSc as module
5286f336411SStefano Zampini
52955a74a43SLisandro Dalcin    lines = Lines()
53055a74a43SLisandro Dalcin    lines.add = IMPORTS
5316f336411SStefano Zampini    lines.add = ''
53255a74a43SLisandro Dalcin    lines.add = visit_module(module)
53355a74a43SLisandro Dalcin    lines.add = TYPING
53455a74a43SLisandro Dalcin    return lines
53555a74a43SLisandro Dalcin
53655a74a43SLisandro Dalcin
53755a74a43SLisandro Dalcindef generate(filename):
53855a74a43SLisandro Dalcin    dirname = os.path.dirname(filename)
53955a74a43SLisandro Dalcin    os.makedirs(dirname, exist_ok=True)
54055a74a43SLisandro Dalcin    with open(filename, 'w') as f:
54155a74a43SLisandro Dalcin        for line in visit_petsc4py_PETSc():
54255a74a43SLisandro Dalcin            print(line, file=f)
54355a74a43SLisandro Dalcin
54455a74a43SLisandro Dalcin
54555a74a43SLisandro DalcinOUTDIR = os.path.join('src', 'petsc4py')
54655a74a43SLisandro Dalcin
54755a74a43SLisandro Dalcinif __name__ == '__main__':
54855a74a43SLisandro Dalcin    generate(os.path.join(OUTDIR, 'PETSc.pyi'))
549