Source code for reflection
# labtools, Copyright (C) 2017 Jerry Fowler and Paul Scheet.
# This program comes with ABSOLUTELY NO WARRANTY. It is licensed under
# GNU GPL Version 3. License and warranty may be viewed in the manual.
'''
A support package for self-reporting
'''
import os
import sys
from collections import defaultdict
import itertools
import logging
from labtools import const
from labtools.labexceptions import LabtoolsWarning, ProgrammingFlawWarning
[docs]def my_methodname():
'''Return the name of the method that invoked this method,
so that it can know its own name.
'''
return sys._getframe(1).f_code.co_name
[docs]def my_callername():
'''Return the name of the caller of the method that invoked this method,
so that it can know its caller's name.
'''
return sys._getframe(2).f_code.co_name
[docs]def typecheck(parameter, *_types):
'''
Test *parameter* for the type given by *_type*, and raise a warning if no match
'''
if not len(_types):
raise ProgrammingFlawWarning('{} got an empty list for _types argument'
.format(my_methodname()))
for _type in _types:
if isinstance(parameter, _type): return _type
message = 'one of {}'.format(_types) if len(_types) > 1 else str(type(_types[0]))
raise ProgrammingFlawWarning('{} got a {}, but requires {}'.format(my_methodname(),
str(type(parameter)),
message))
def iteration(stream):
try:
line = next(stream)
while line is not None:
yield line
line = next(stream)
except StopIteration:
pass
[docs]def constant_iterator(constant):
'''
utility function to allow simple specification of a constant generator
*constant* the constant to be repeatedly generated
'''
return itertools.repeat(constant).__next__
[docs]def constant_dict(constant):
'''
allow simple specification of a defaultdict that uses a constant generator
to default to the given constant.
*constant* the constant to be repeatedly generated
'''
return defaultdict(constant_iterator(constant))
[docs]class Namespace():
'''
Provide a cheap trivially repeatable namespace. I don't know
why a module or program would need two, but you can name it.
This probably lurks formally in python modules somewhere...
'''
def __init__(self, name='anonymous', **kwargs):
self.name = name
for k in list(kwargs.keys()):
eval("self.%s = '%s'" % (k, kwargs[k]))
[docs]def save_trace(e, printit='ignore', tmpdir='/var/tmp', dumpfile=None):
'''
I believe it would be useful to have this generally, but it is
as yet not completely spec'd except for a special case in syqada
that differs from this one.
currently raises not implemented
'''
import traceback
raise LabtoolsWarning('%s not implemented' % (my_methodname()))
type, value, tb = sys.exc_info()
if dumpfile is None:
dumpfile = '%s.dump' % (os.path.basename(sys.argv[0]))
dumpfile = os.path.join(tmpdir, dumpfile)
print(e)
if not isinstance(e, LabtoolsWarning):
with open(dumpfile, const.WRITE) as dump:
traceback.print_exception(type, value, tb, file=dump)