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)