Create delegated pyi

Setup

Basics


source

imp_mod

 imp_mod (module_path, package=None)

Import dynamically the module referenced in fn

fn = Path('test_py2pyi.py')
mod = imp_mod(fn)
a = mod.A()
a.h()
1
tree = _get_tree(mod)

AST.__repr__

 AST.__repr__ ()
# for o in enumerate(tree.body): print(o)
node = tree.body[4]
node
def f(a: int, b: str='a') -> str:
    """I am f"""
    return 1
isinstance(node, functypes)
True

source

has_deco

 has_deco (node:Union[ast.FunctionDef,ast.AsyncFunctionDef], name:str)

Check if a function node node has a decorator named name

nm = 'delegates'
has_deco(node, nm)
False
node = tree.body[5]
node
@delegates(f)
def g(c, d: X, **kwargs) -> str:
    """I am g"""
    return 2
has_deco(node, nm)
True

Function processing

def _proc_body   (node, mod): print('_proc_body', type(node))
def _proc_func   (node, mod): print('_proc_func', type(node))
def _proc_class  (node, mod): print('_proc_class', type(node))
def _proc_patched(node, mod): print('_proc_patched', type(node))
_proc_mod(mod);
_proc_class <class 'ast.ClassDef'>
_proc_body <class 'ast.FunctionDef'>
_proc_func <class 'ast.FunctionDef'>
_proc_body <class 'ast.FunctionDef'>
_proc_class <class 'ast.ClassDef'>
_proc_class <class 'ast.ClassDef'>
_proc_patched <class 'ast.FunctionDef'>
_proc_patched <class 'ast.FunctionDef'>
_proc_body <class 'ast.FunctionDef'>
node.name
'g'
sym = getattr(mod, node.name)
sym
<function test_py2pyi.g(c, d: test_py2pyi.X, *, b: str = 'a') -> str>
sig = signature(sym)
print(sig)
(c, d: test_py2pyi.X, *, b: str = 'a') -> str

source

sig2str

 sig2str (sig)

source

ast_args

 ast_args (func)
newargs = ast_args(sym)
newargs
c, d: test_py2pyi.X, *, b: str='a'
node.args
c, d: X, **kwargs
node.args = newargs
node
@delegates(f)
def g(c, d: test_py2pyi.X, *, b: str='a') -> str:
    """I am g"""
    return 2
_body_ellip(node)
node
@delegates(f)
def g(c, d: test_py2pyi.X, *, b: str='a') -> str:
    """I am g"""
    ...
tree = _get_tree(mod)
node = tree.body[5]
node
@delegates(f)
def g(c, d: X, **kwargs) -> str:
    """I am g"""
    return 2
_update_func(node, sym)
node
def g(c, d: test_py2pyi.X, *, b: str='a') -> str:
    """I am g"""
    ...
tree = _proc_mod(mod)
tree.body[5]
_proc_class <class 'ast.ClassDef'>
_proc_class <class 'ast.ClassDef'>
_proc_class <class 'ast.ClassDef'>
_proc_patched <class 'ast.FunctionDef'>
_proc_patched <class 'ast.FunctionDef'>
def g(c, d: test_py2pyi.X, *, b: str='a') -> str:
    """I am g"""
    ...

Patch

node = tree.body[9]
node
@patch
@delegates(j)
def k(self: (A, B), b: bool=False, **kwargs):
    return 1
ann = node.args.args[0].annotation
if hasattr(ann, 'elts'): ann = ann.elts[0]
nm = ann.id
nm
'A'
cls = getattr(mod, nm)
sym = getattr(cls, node.name)
sig2str(signature(sym))
"(self: (test_py2pyi.A, test_py2pyi.B), b: bool = False, *, d: str = 'a')"
_update_func(node, sym)
node
@patch
def k(self: (test_py2pyi.A, test_py2pyi.B), b: bool=False, *, d: str='a'):
    ...
tree = _proc_mod(mod)
tree.body[9]
_proc_class <class 'ast.ClassDef'>
_proc_class <class 'ast.ClassDef'>
_proc_class <class 'ast.ClassDef'>
@patch
def k(self: (test_py2pyi.A, test_py2pyi.B), b: bool=False, *, d: str='a'):
    ...

Class and file

tree = _get_tree(mod)
node = tree.body[7]
node
class A:

    @delegates(j)
    def h(self, b: bool=False, **kwargs):
        a = 1
        return a
node.body
[@delegates(j)
 def h(self, b: bool=False, **kwargs):
     a = 1
     return a]
tree = _proc_mod(mod)
tree.body[7]
class A:

    def h(self, b: bool=False, *, d: str='a'):
        ...

source

create_pyi

 create_pyi (fn, package=None)

Convert fname.py to fname.pyi by removing function bodies and expanding delegates kwargs

create_pyi(fn)
# fn = Path('/Users/jhoward/git/fastcore/fastcore/docments.py')
# create_pyi(fn, 'fastcore')

Script


source

py2pyi

 py2pyi (fname:str, package:str=None)

Convert fname.py to fname.pyi by removing function bodies and expanding delegates kwargs

Type Default Details
fname str The file name to convert
package str None The parent package

source

replace_wildcards

 replace_wildcards (path:str)

Expand wildcard imports in the specified Python file.

Type Details
path str Path to the Python file to process