Skip to content

Instantly share code, notes, and snippets.

@anthonyrisinger
Created March 14, 2014 21:00
Show Gist options
  • Save anthonyrisinger/9556806 to your computer and use it in GitHub Desktop.
Save anthonyrisinger/9556806 to your computer and use it in GitHub Desktop.
Function-like Modules (better control/introspection)
# encoding: utf-8
#
# modules-next
#
# C Anthony Risinger
import sys
m_name = 'modules_next'
m_source = r"""\
if __name__ == '{0}':
from . import __call__ as reexec
from . import __code__ as code
from . import __dict__ as ns
print('>>> {{0}}: {{1}}\n{{2}}\n'.format(__name__, code, ns.keys()))
__name__ = 'modules_next_reloaded'
reexec()
print('>>> {{0}}: {{1}}\n{{2}}\n'.format(__name__, code, ns.keys()))
else:
print('!!! __name__ == {{0}}\n'.format(__name__))
def throw():
raise Exception(__name__)
""".format(m_name)
m_code = compile(m_source, m_name, 'exec')
m_dict = {
'__file__': __file__ + '.next',
'__name__': m_name,
'__path__': list(),
'__doc__': None,
}
#...bind namespace/functions
module = eval('lambda: None', m_dict)
#...automatically expose as attributes
module.__dict__ = module.__globals__
#...must be set twice, __code__ sees __dict__, but we see descriptor
module.__name__ = m_name
#...redefine the function body!
module.__code__ = m_code
#...yay! we haz legitimate module!
sys.modules[m_name] = module
print('--* importing...')
import modules_next
print('>>> {0}: {1}\n{2}\n'.format(
__name__,
modules_next.__code__,
modules_next.__dict__.keys(),
))
print('--* importing (for real this time)...')
#...import/reload by calling our func-y-module
module()
print('>>> {0}: {1}\n{2}\n'.format(
__name__,
modules_next.__code__,
modules_next.__dict__.keys(),
))
print('--* throwing...')
modules_next.throw()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment