#!/usr/local/bin/python3.13
#
# Author: Mike McKerns (mmckerns @caltech and @uqfoundation)
# Copyright (c) 2008-2016 California Institute of Technology.
# Copyright (c) 2016-2026 The Uncertainty Quantification Foundation.
# License: 3-clause BSD.  The full license text is available at:
#  - https://github.com/uqfoundation/dill/blob/master/LICENSE
'''
build profile graph for the given instance

running:
  $ get_gprof <args> <instance>

executes:
  gprof2dot -f pstats <args> <type>.prof | dot -Tpng -o <type>.call.png

where:
  <args> are arguments for gprof2dot, such as "-n 5 -e 5"
  <instance> is code to create the instance to profile
  <type> is the class of the instance (i.e. type(instance))

For example:
  $ get_gprof -n 5 -e 1 "import numpy; numpy.array([1,2])"

will create 'ndarray.call.png' with the profile graph for numpy.array([1,2]),
where '-n 5' eliminates nodes below 5% threshold, similarly '-e 1' eliminates
edges below 1% threshold
'''

if __name__ == "__main__":
    import sys
    if len(sys.argv) < 2:
        print ("Please provide an object instance (e.g. 'import math; math.pi')")
        sys.exit()
    # grab args for gprof2dot
    args = sys.argv[1:-1]
    args = ' '.join(args)
    # last arg builds the object
    obj = sys.argv[-1]
    obj = obj.split(';')
    # multi-line prep for generating an instance
    for line in obj[:-1]:
        exec(line)
    # one-line generation of an instance
    try:
        obj = eval(obj[-1])
    except Exception:
        print ("Error processing object instance")
        sys.exit()

    # get object 'name'
    objtype = type(obj)
    name = getattr(objtype, '__name__', getattr(objtype, '__class__', objtype))

    # profile dumping an object
    import dill
    import os
    import cProfile
    #name = os.path.splitext(os.path.basename(__file__))[0]
    cProfile.run("dill.dumps(obj)", filename="%s.prof" % name)
    msg = "gprof2dot -f pstats %s %s.prof | dot -Tpng -o %s.call.png" % (args, name, name)
    try:
        res = os.system(msg)
    except Exception:
        print ("Please verify install of 'gprof2dot' to view profile graphs")
    if res:
        print ("Please verify install of 'gprof2dot' to view profile graphs")

    # get stats
    f_prof = "%s.prof" % name
    import pstats
    stats = pstats.Stats(f_prof, stream=sys.stdout)
    stats.strip_dirs().sort_stats('cumtime')
    stats.print_stats(20) #XXX: save to file instead of print top 20?
    os.remove(f_prof)
