<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step4:  The inspect module provides functions for learning about live objects, classes, instances, and methods. The functions in this module can be used to retrieve the original source code for a function, look the arguments to a method on the stack, and extract the sort of information useful for producing library documentation for source code.
Example code
Step5:  The first kind of introspection probes live objects to learn about them. Use getmembers() to discover the member attributes of object. The types of members that might be returned depend on the type of object scanned. Modules can contain classes and functions; classes can contain methods and attributes; and so on.
The arguments to getmembers() are an object to scan (a module, class, or instance) and an optional predicate function that is used to filter the objects returned. The return value is a list of tuples with two values
Step6:  The predicate argument can be used to filter the types of objects returned.
Step7:  Inspecting Classes
Classes are scanned using getmembers() in the same way as modules, though the types of members are different.
Step8:  To find the methods of a class, use the isfunction() predicate. The ismethod() predicate only recognizes bound methods of instances.
Step9:  The output for B includes the override for get_name() as well as the new method, and the inherited init() method implemented in A.
Step10:  Inspecting Instances
Introspecting instances works in the same way as other objects.
Step11:  Documentation Strings
The docstring for an object can be retrieved with getdoc(). The return value is the doc attribute with tabs expanded to spaces and with indentation made uniform.
Step12:  The second line of the docstring is indented when it is retrieved through the attribute directly, but moved to the left margin by getdoc().
In addition to the actual docstring, it is possible to retrieve the comments from the source file where an object is implemented, if the source is available. The getcomments() function looks at the source of the object and finds comments on lines preceding the implementation.
Step13:  Retrieving Source
If the .py file is available for a module, the original source code for the class or method can be retrieved using getsource() and getsourcelines().
Step14:  To retrieve the source for a single method, pass the method reference to getsource().
Step15:  Use getsourcelines() instead of getsource() to retrieve the lines of source split into individual strings.
Step16:  Method and Function Signatures
In addition to the documentation for a function or method, it is possible to ask for a complete specification of the arguments the callable takes, including default values. The signature() function returns a Signature instance containing information about the arguments to the function.
Step17:  The function arguments are available through the parameters attribute of the Signature. parameters is an ordered dictionary mapping the parameter names to Parameter instances describing the argument. In this example, the first argument to the function, arg1, does not have a default value, while arg2 does.
The Signature for a function can be used by decorators or other functions to validate inputs, provide different defaults, etc. Writing a suitably generic and reusable validation decorator has one special challenge, though, because it can be complicated to match up incoming arguments with their names for functions that accept a combination of named and positional arguments. The bind() and bind_partial() methods provide the necessary logic to handle the mapping. They return a BoundArguments instance populated with the arguments associated with the names of the arguments of a specified function.
Step18:  Class Hierarchies
inspect includes two methods for working directly with class hierarchies. The first, getclasstree(), creates a tree-like data structure based on the classes it is given and their base classes. Each element in the list returned is either a tuple with a class and its base classes, or another list containing tuples for subclasses.
Step19:  The output from this example is the tree of inheritance for the A, B, C, and D classes. D appears twice, since it inherits from both C and A.
If getclasstree() is called with unique set to a true value, the output is different.
Step20:  Method Resolution Order
The other function for working with class hierarchies is getmro(), which returns a tuple of classes in the order they should be scanned when resolving an attribute that might be inherited from a base class using the Method Resolution Order (MRO). Each class in the sequence appears only once.
Step21:  The Stack and Frames
In addition to introspection of code objects, inspect includes functions for inspecting the runtime environment while a program is being executed. Most of these functions work with the call stack, and operate on call frames. Frame objects hold the current execution context, including references to the code being run, the operation being executed, as well as the values of local and global variables. Typically such information is used to build tracebacks when exceptions are raised. It can also be useful for logging or when debugging programs, since the stack frames can be interrogated to discover the argument values passed into the functions.
currentframe() returns the frame at the top of the stack (for the current function).
Step22:  Using stack(), it is also possible to access all of the stack frames from the current frame to the first caller. This example is similar to the one shown earlier, except it waits until reaching the end of the recursion to print the stack information.
Step23:  There are other functions for building lists of frames in different contexts, such as when an exception is being processed. See the documentation for trace(), getouterframes(), and getinnerframes() for more details.
Command Line Interface
The inspect module also includes a command line interface for getting details about objects without having to write out the calls in a separate Python program. The input is a module name and optional object from within the module. The default output is the source code for the named object. Using the --details argument causes metadata to be printed instead of the source.
<ASSISTANT_TASK:>
Python Code:
# %load example.py
def module_level_function(arg1, arg2='default', *args, **kwargs):
    This function is declared in the module.
    local_variable = arg1 * 2
    return local_variable
class A(object):
    The A class.
    def __init__(self, name):
        self.name = name
    def get_name(self):
        "Returns the name of the instance."
        return self.name
instance_of_a = A('sample_instance')
class B(A):
    This is the B class.
    It is derived from A.
    
    # This method is not part of A.
    def do_something(self):
        Does some work
    def get_name(self):
        "Overrides version from A"
        return 'B(' + self.name + ')'
Explanation: The inspect module provides functions for learning about live objects, classes, instances, and methods. The functions in this module can be used to retrieve the original source code for a function, look the arguments to a method on the stack, and extract the sort of information useful for producing library documentation for source code.
Example code
End of explanation
import inspect
import example
for name, data in inspect.getmembers(example):
    if name.startswith('__'):
        continue
    print('{} : {!r}'.format(name, data))
Explanation: The first kind of introspection probes live objects to learn about them. Use getmembers() to discover the member attributes of object. The types of members that might be returned depend on the type of object scanned. Modules can contain classes and functions; classes can contain methods and attributes; and so on.
The arguments to getmembers() are an object to scan (a module, class, or instance) and an optional predicate function that is used to filter the objects returned. The return value is a list of tuples with two values: the name of the member, and the type of the member. The inspect module includes several such predicate functions with names like ismodule(), isclass(), etc.
End of explanation
import inspect
import example
for name, data in inspect.getmembers(example, inspect.isclass):
    print('{} : {!r}'.format(name, data))
Explanation: The predicate argument can be used to filter the types of objects returned.
End of explanation
import inspect
from pprint import pprint
import example
pprint(inspect.getmembers(example.A), width=65)
Explanation: Inspecting Classes
Classes are scanned using getmembers() in the same way as modules, though the types of members are different.
End of explanation
import inspect
from pprint import pprint
import example
pprint(inspect.getmembers(example.A, inspect.isfunction))
Explanation: To find the methods of a class, use the isfunction() predicate. The ismethod() predicate only recognizes bound methods of instances.
End of explanation
import inspect
from pprint import pprint
import example
pprint(inspect.getmembers(example.B, inspect.isfunction))
Explanation: The output for B includes the override for get_name() as well as the new method, and the inherited init() method implemented in A.
End of explanation
import inspect
from pprint import pprint
import example
a = example.A(name='inspect_getmembers')
pprint(inspect.getmembers(a, inspect.ismethod))
Explanation: Inspecting Instances
Introspecting instances works in the same way as other objects.
End of explanation
import inspect
import example
print('B.__doc__:')
print(example.B.__doc__)
print()
print('getdoc(B):')
print(inspect.getdoc(example.B))
Explanation: Documentation Strings
The docstring for an object can be retrieved with getdoc(). The return value is the doc attribute with tabs expanded to spaces and with indentation made uniform.
End of explanation
import inspect
import example
print(inspect.getcomments(example.B.do_something))
Explanation: The second line of the docstring is indented when it is retrieved through the attribute directly, but moved to the left margin by getdoc().
In addition to the actual docstring, it is possible to retrieve the comments from the source file where an object is implemented, if the source is available. The getcomments() function looks at the source of the object and finds comments on lines preceding the implementation.
End of explanation
import inspect
import example
print(inspect.getsource(example.A))
Explanation: Retrieving Source
If the .py file is available for a module, the original source code for the class or method can be retrieved using getsource() and getsourcelines().
End of explanation
import inspect
import example
print(inspect.getsource(example.A.get_name))
Explanation: To retrieve the source for a single method, pass the method reference to getsource().
End of explanation
import inspect
import pprint
import example
pprint.pprint(inspect.getsourcelines(example.A.get_name))
Explanation: Use getsourcelines() instead of getsource() to retrieve the lines of source split into individual strings.
End of explanation
import inspect
import example
sig = inspect.signature(example.module_level_function)
print('module_level_function{}'.format(sig))
print('\nParameter details:')
for name, param in sig.parameters.items():
    if param.kind == inspect.Parameter.POSITIONAL_ONLY:
        print('  {} (positional-only)'.format(name))
    elif param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
        if param.default != inspect.Parameter.empty:
            print('  {}={!r}'.format(name, param.default))
        else:
            print('  {}'.format(name))
    elif param.kind == inspect.Parameter.VAR_POSITIONAL:
        print('  *{}'.format(name))
    elif param.kind == inspect.Parameter.KEYWORD_ONLY:
        if param.default != inspect.Parameter.empty:
            print('  {}={!r} (keyword-only)'.format(
                name, param.default))
        else:
            print('  {} (keyword-only)'.format(name))
    elif param.kind == inspect.Parameter.VAR_KEYWORD:
        print('  **{}'.format(name))
Explanation: Method and Function Signatures
In addition to the documentation for a function or method, it is possible to ask for a complete specification of the arguments the callable takes, including default values. The signature() function returns a Signature instance containing information about the arguments to the function.
End of explanation
import inspect
import example
sig = inspect.signature(example.module_level_function)
bound = sig.bind(
    'this is arg1',
    'this is arg2',
    'this is an extra positional argument',
    extra_named_arg='value',
)
print('Arguments:')
for name, value in bound.arguments.items():
    print('{} = {!r}'.format(name, value))
print('\nCalling:')
print(example.module_level_function(*bound.args, **bound.kwargs))
Explanation: The function arguments are available through the parameters attribute of the Signature. parameters is an ordered dictionary mapping the parameter names to Parameter instances describing the argument. In this example, the first argument to the function, arg1, does not have a default value, while arg2 does.
The Signature for a function can be used by decorators or other functions to validate inputs, provide different defaults, etc. Writing a suitably generic and reusable validation decorator has one special challenge, though, because it can be complicated to match up incoming arguments with their names for functions that accept a combination of named and positional arguments. The bind() and bind_partial() methods provide the necessary logic to handle the mapping. They return a BoundArguments instance populated with the arguments associated with the names of the arguments of a specified function.
End of explanation
import inspect
import example
class C(example.B):
    pass
class D(C, example.A):
    pass
def print_class_tree(tree, indent=-1):
    if isinstance(tree, list):
        for node in tree:
            print_class_tree(node, indent + 1)
    else:
        print('  ' * indent, tree[0].__name__)
    return
if __name__ == '__main__':
    print('A, B, C, D:')
    print_class_tree(inspect.getclasstree(
        [example.A, example.B, C, D])
    )
Explanation: Class Hierarchies
inspect includes two methods for working directly with class hierarchies. The first, getclasstree(), creates a tree-like data structure based on the classes it is given and their base classes. Each element in the list returned is either a tuple with a class and its base classes, or another list containing tuples for subclasses.
End of explanation
import inspect
import example
print_class_tree(inspect.getclasstree(
    [example.A, example.B, C, D],
    unique=True,
))
Explanation: The output from this example is the tree of inheritance for the A, B, C, and D classes. D appears twice, since it inherits from both C and A.
If getclasstree() is called with unique set to a true value, the output is different.
End of explanation
import inspect
import example
class C(object):
    pass
class C_First(C, example.B):
    pass
class B_First(example.B, C):
    pass
print('B_First:')
for c in inspect.getmro(B_First):
    print('  {}'.format(c.__name__))
print()
print('C_First:')
for c in inspect.getmro(C_First):
    print('  {}'.format(c.__name__))
Explanation: Method Resolution Order
The other function for working with class hierarchies is getmro(), which returns a tuple of classes in the order they should be scanned when resolving an attribute that might be inherited from a base class using the Method Resolution Order (MRO). Each class in the sequence appears only once.
End of explanation
import inspect
import pprint
def recurse(limit, keyword='default', *, kwonly='must be named'):
    local_variable = '.' * limit
    keyword = 'changed value of argument'
    frame = inspect.currentframe()
    print('line {} of {}'.format(frame.f_lineno,
                                 frame.f_code.co_filename))
    print('locals:')
    pprint.pprint(frame.f_locals)
    print()
    if limit <= 0:
        return
    recurse(limit - 1)
    return local_variable
if __name__ == '__main__':
    recurse(2)
Explanation: The Stack and Frames
In addition to introspection of code objects, inspect includes functions for inspecting the runtime environment while a program is being executed. Most of these functions work with the call stack, and operate on call frames. Frame objects hold the current execution context, including references to the code being run, the operation being executed, as well as the values of local and global variables. Typically such information is used to build tracebacks when exceptions are raised. It can also be useful for logging or when debugging programs, since the stack frames can be interrogated to discover the argument values passed into the functions.
currentframe() returns the frame at the top of the stack (for the current function).
End of explanation
import inspect
import pprint
def show_stack():
    for level in inspect.stack():
        print('{}[{}]\n  -> {}'.format(
            level.frame.f_code.co_filename,
            level.lineno,
            level.code_context[level.index].strip(),
        ))
        pprint.pprint(level.frame.f_locals)
        print()
def recurse(limit):
    local_variable = '.' * limit
    if limit <= 0:
        show_stack()
        return
    recurse(limit - 1)
    return local_variable
if __name__ == '__main__':
    recurse(2)
Explanation: Using stack(), it is also possible to access all of the stack frames from the current frame to the first caller. This example is similar to the one shown earlier, except it waits until reaching the end of the recursion to print the stack information.
End of explanation
!python3 -m inspect -d example
!python3 -m inspect -d example:A
!python3 -m inspect example:A.get_name
Explanation: There are other functions for building lists of frames in different contexts, such as when an exception is being processed. See the documentation for trace(), getouterframes(), and getinnerframes() for more details.
Command Line Interface
The inspect module also includes a command line interface for getting details about objects without having to write out the calls in a separate Python program. The input is a module name and optional object from within the module. The default output is the source code for the named object. Using the --details argument causes metadata to be printed instead of the source.
End of explanation
<END_TASK>