Skip to content

Instantly share code, notes, and snippets.

@miki725
Last active January 5, 2018 17:04
Show Gist options
  • Save miki725/08546c625876f055d98bc6ef9d194d48 to your computer and use it in GitHub Desktop.
Save miki725/08546c625876f055d98bc6ef9d194d48 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
import inspect
from importlib import import_module
import click
click.disable_unicode_literals_warning = True
def parse_dot(path):
module, klass_and_method = path.split(':')
klass, method = klass_and_method.split('.')
return module, klass, method
def parse_pycharm(path):
module_and_klass, method = path.split('#')
module, klass = module_and_klass.rsplit('.', 1)
return module, klass, method
parse_mapping = {
'dot': parse_dot,
'pycharm': parse_pycharm,
}
def print_method(klass, method):
source = inspect.getsource(method)
lines = source.splitlines()
indent = len(lines[0]) - len(lines[0].lstrip(' \t'))
lines = [i[indent:] for i in lines]
header = '{}.{}.{}'.format(klass.__module__, klass.__name__, method.__name__)
print('-' * len(header))
print(header)
print('-' * len(header))
print('\n'.join(lines))
@click.command()
@click.argument(
'path',
metavar='METHOD_PATH',
)
@click.option(
'--pre',
metavar='CODE',
help="""
Arbitrary python statements to exec before importing module.
"""
)
@click.option(
'--django',
is_flag=True,
default=False,
help="""
Initialize django before importing modules.
"""
)
@click.option(
'--path-style',
default='dot',
type=click.Choice(['dot', 'pycharm']),
help="""
Style in which path is provided.
* dot - standard dot-notation (e.g. "module.path:Class.method")
* pycharm - PyCharm notation (e.g. "module.path.Class#method")
"""
)
def mro_method(path, pre, django, path_style):
"""
Get all method definitions within class method mro
Useful to inspect classes with complex mro order.
Method path can be provided in normal Python dot notation:
"module.path:Class.method".
Alternatively PyCharm style "module.path.Class#method" is also supported.
"""
module, klass, method = parse_mapping[path_style](path)
if django:
import django
django.setup()
if pre:
exec(pre)
module = import_module(module)
klass = getattr(module, klass)
print('========')
print('Full MRO')
print('========')
for c in klass.mro():
print('{}.{}'.format(c.__module__, c.__name__))
print()
for c in klass.mro():
m = c.__dict__.get(method)
if not m:
continue
print_method(c, m)
print()
if __name__ == '__main__':
mro_method()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment