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