Printing FastHTML Components

from fasthtml.common import *
btn = Button("Click me", "btn btn-primary")
btn
<button>
Click me
btn btn-primary
</button>
type(btn)
fastcore.xml.FT
str(btn)
"['button', ('Click me', 'btn btn-primary'), {}]"

Reading https://github.com/fastai/fastcore/blob/master/fastcore/xml.py and https://github.com/fastai/fastcore/blob/master/nbs/11_xml.ipynb I see that an XT is a list with some properties:

btn.tag
'button'
btn.children
('Click me', 'btn btn-primary')
btn.attrs
{}

Oh, I think I can use this to show the rendered component XML:

to_xml(btn)
'<button>\nClick me\nbtn btn-primary\n</button>\n'
highlight(btn)
'```xml\n<button>\nClick me\nbtn btn-primary\n</button>\n\n```'

What about stringifying the Python code for a component?

import inspect
print(inspect.getsource(btn))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 3
      1 #|eval: false
      2 import inspect
----> 3 print(inspect.getsource(btn))

File /usr/local/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/python3.12/inspect.py:1279, in getsource(object)
   1273 def getsource(object):
   1274     """Return the text of the source code for an object.
   1275 
   1276     The argument may be a module, class, method, function, traceback, frame,
   1277     or code object.  The source code is returned as a single string.  An
   1278     OSError is raised if the source code cannot be retrieved."""
-> 1279     lines, lnum = getsourcelines(object)
   1280     return ''.join(lines)

File /usr/local/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/python3.12/inspect.py:1261, in getsourcelines(object)
   1253 """Return a list of source lines and starting line number for an object.
   1254 
   1255 The argument may be a module, class, method, function, traceback, frame,
   (...)
   1258 original source file the first line of code was found.  An OSError is
   1259 raised if the source code cannot be retrieved."""
   1260 object = unwrap(object)
-> 1261 lines, lnum = findsource(object)
   1263 if istraceback(object):
   1264     object = object.tb_frame

File /usr/local/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/python3.12/inspect.py:1072, in findsource(object)
   1064 def findsource(object):
   1065     """Return the entire source file and starting line number for an object.
   1066 
   1067     The argument may be a module, class, method, function, traceback, frame,
   1068     or code object.  The source code is returned as a list of all the lines
   1069     in the file and the line number indexes a line in that list.  An OSError
   1070     is raised if the source code cannot be retrieved."""
-> 1072     file = getsourcefile(object)
   1073     if file:
   1074         # Invalidate cache if needed.
   1075         linecache.checkcache(file)

File /usr/local/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/python3.12/inspect.py:949, in getsourcefile(object)
    945 def getsourcefile(object):
    946     """Return the filename that can be used to locate an object's source.
    947     Return None if no way can be identified to get the source.
    948     """
--> 949     filename = getfile(object)
    950     all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:]
    951     all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:]

File /usr/local/Cellar/python@3.12/3.12.4/Frameworks/Python.framework/Versions/3.12/lib/python3.12/inspect.py:929, in getfile(object)
    927 if iscode(object):
    928     return object.co_filename
--> 929 raise TypeError('module, class, method, function, traceback, frame, or '
    930                 'code object was expected, got {}'.format(
    931                 type(object).__name__))

TypeError: module, class, method, function, traceback, frame, or code object was expected, got FT