May-05-2017, 05:37 AM
this is the print_object() function i have been revising, as mentioned in another thread:
#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function """ Module to print objects like dictionaries and lists, nicely. """ license = """ Copyright © 2017, by Phil D. Howard - all other rights reserved Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. The author may be contacted using the short first name, middle initial, and last name, separated by periods, with gmail dot com as the host part of an email address. """ import os,sys,time debug = not os.environ.get('nodebug',False) ex = BrokenPipeError if sys.version_info.major > 2 else IOError stderr = sys.stderr #----------------------------------------------------------------------- # file printobject.py # module printobject # import from printobject import print_object #----------------------------------------------------------------------- from sys import argv, stderr, stdout, version_info ver = version_info.major if ver < 3: bytes = bytearray if ver > 2: unicode = str long = int flush = stdout.flush empty_text = 'EMPTY' end_of_text = 'end of' NoneType = type(None) #---------------------------------------------------------------------- # function __sortkey__ # purpose key map so types are separate # note avoid importing decimal by the following cheat. # cheat decimal.Decimal is tested by attribute 'exp' existing. # note recode this to change mixed type ordering. #---------------------------------------------------------------------- def __sortkey__(k): if isinstance(k,NoneType): return (16,k) if isinstance(k,bool): return (17,k) if isinstance(k,int): return (32,k) if isinstance(k,long): return (33,k) if isinstance(k,float): return (34,k) if isinstance(k,complex): return (35,k) if isinstance(k,str): return (48,k) if isinstance(k,unicode): return (49,k) if isinstance(k,bytearray): return (50,k) if isinstance(k,bytes): return (51,k) if 'exp' in dir(k): return (64,k) try: return (96,hash(k)) except TypeError: return (99,0) #---------------------------------------------------------------------- # function __repr__ # purpose Handle every exception repr() throws to return a string # that represents an issue with repr() gracefully. Also # handle an emtpy or non-string return value similarly. # usage just like repr() #---------------------------------------------------------------------- def __repr__(o): try: return repr(o) except: return '<unknown>' #---------------------------------------------------------------------- # function print_object # purpose Print a Python data object in an easily readable # consistent code format. # note strings are appended with their length in a splice # format (so it is still valid code). # import from printobject import print_object # usage callable function, in place of repr() and print() # arguments 1 (...) object to be printed # options file= file to output to # indent= (int, default=0) how many spaces to indent # format to the right # name= the name of the object to be printed (a dict # key unless ending with '=') # note if name option ends with an append '=' then the # output code is a variable assignment. # returns None # features 1: output can be used as Python code # 2: dictionary members are output in key-sorted order # 3: length of strings and lists are shown # 4: data element types are shown #---------------------------------------------------------------------- def print_object( *args, **opts ): # the object to be printed obj = args[0] comment = '#' popt = {} # set up options 'filename' and 'file' close = False def_file = stdout filename = opts.pop('filename',False) if isinstance(filename,str): if '.' not in filename: filename = filename + '.po' try: def_file = open( filename, 'w' ) close = True except IOError: return None file = opts.pop('file',def_file) opts['file'] = file popt['file'] = file flush = opts.pop('flush',False) if isinstance(flush,str): if flush.lower() in ('no','false'): flush = flush.lower() not in ('no','false') if isinstance(flush,(int,float)): flush = False if flush == 0 else True comma = opts.pop('comma',',') user_cmnt = opts.pop('comment','') depth = opts.pop('depth',0) asdict = opts.pop('dict',False) indent = opts.pop('indent',0) index = opts.pop('index',None) name = opts.pop('name','object') namewidth = opts.pop('namewidth',False) maxdepth = opts.pop('maxdepth',0x7fffffffffffffff) if maxdepth < 1: print( 'deeper objects not printed', **popt ) return None if isinstance(index,int): comment = '#' + str(index) if asdict: stdout.flush() if isinstance(name,(str,unicode,bytearray,bytes,list,tuple)): prefix = repr(name) + '[:' + str(len(name)) + ']:' else: prefix = repr(name) + ':' else: if depth < 1: if isinstance(name,str): prefix = name + ' = ' else: prefix = __repr__(name) + ' = ' else: prefix = ' ' if namewidth: prelen = len(prefix) if prelen < namewidth: prefix += (namewidth-prelen)*' ' prefix = indent * ' ' + prefix prelen = len(prefix) spaces = prelen * ' ' # leftover options might be intended for print() for k,v in opts.items(): popt[k] = v # nothing (no args) passed to be printed: print an empty line if len(args) < 1: print( **popt ) stdout.flush() return None opts['depth'] = depth + 1 #---------------------------------------------------------------------- # dictionary: # print one line for each member, in sorted-key order. # print both key and value with space padding for vertical line-up. # call print_object() recursively to format values the same way. #---------------------------------------------------------------------- if isinstance(obj,dict): if len( obj ) == 0: print( prefix+ '{},', comment, empty_text, 'dict'+ user_cmnt, **popt ) else: print( prefix+ '{', comment, 'dict'+ user_cmnt, 'len =', len( obj ), **popt ) # determine the width to use w = 0 for k in obj.keys(): if 'split' in dir(k): # if k is a string w = max( w, len(__repr__(k))+ len(__repr__(len(k)))+5 ) else: w = max( w, len(__repr__(k))+2 ) for k,v in sorted(obj.items(),key=__sortkey__): print_object( v, name=k, dict=True, indent=prelen+2, namewidth=w, **opts ) print( spaces + '}' + comma, comment, end_of_text, 'dict', 'len =', len( obj ), **popt ) #---------------------------------------------------------------------- # set: # print one line for each member, in sorted-key order # with space padding for vertical line-up. #---------------------------------------------------------------------- elif isinstance(obj,set): if len( obj ) == 0: print( prefix+ 'set([]),', comment, empty_text, 'set'+ user_cmnt, **popt ) else: print( prefix+ '{', comment, 'set'+ user_cmnt, 'len =', len( obj ), **popt ) # determine the width to use w = 0 for k in obj: w = max( w ,len(__repr__(k))+5 ) for m in sorted(obj,key=__sortkey__): print( spaces+ ' '+ __repr__(m)+ comma, comment, 'set'+ user_cmnt, **popt ) print( spaces+ '}'+ comma, comment, end_of_text, 'set', 'len =', len( obj ), **popt ) #---------------------------------------------------------------------- # bytearray: # print bytes with escape sequence coding for unprintable bytes. # append slicing code that shows the length as a full slice. #---------------------------------------------------------------------- elif isinstance(obj,bytearray): if len(obj) < 1: print( prefix+ "bytearray(b'')[:0]"+ comma, comment, empty_text, 'bytearray'+ user_cmnt, **popt ) else: v = "bytearray(b'" for n in obj: v += (repr(chr(n)) if ver < 3 else ascii(chr(n)))[1:-1] v += "')[:" + str(len(obj)) + ']' print( prefix+ v+ comma, comment, 'bytearray'+ user_cmnt, **popt ) #---------------------------------------------------------------------- # bytes (in Python3 only): # print bytes with escape sequence coding for unprintable bytes. # append slicing code that shows the length as a full slice. #---------------------------------------------------------------------- elif ver > 2 and isinstance(obj,bytes): if len(obj) < 1: print( prefix+ "b''[:0]"+ comma, comment, empty_text, 'bytes'+ user_cmnt, **popt ) else: v = "'" for n in obj: v += ascii(chr(n))[1:-1] v += "'[:" + str(len(obj)) + ']' print( prefix+ v+ comma, comment, 'bytes'+ user_cmnt, **popt ) #---------------------------------------------------------------------- # unicode string: # print characters with escape sequence coding for unprintable ones. # append slicing code that shows the length as a full slice. #---------------------------------------------------------------------- elif ver < 3 and isinstance(obj,unicode): if len(obj) < 1: print( prefix+ "u''[:0]"+ comma, comment, empty_text, 'unicode'+ user_cmnt, **popt ) else: v = "'" for x in obj: n = ord(x) if n < 256: v += (repr(x) if ver < 3 else ascii(x))[1:-1] elif n < 65536: v += '\\u%04x' % (n,) else: v += '\\U%08x' % (n,) v += "'[:" + str(len(obj)) + ']' print( prefix+ v+ comma, comment, 'str'+ user_cmnt, **popt ) #---------------------------------------------------------------------- # string: # print characters with escape sequence coding for unprintable ones. # append slicing code that shows the length as a full slice. #---------------------------------------------------------------------- elif isinstance(obj,str): if len(obj) < 1: print( prefix+ "''[:0]"+ comma, comment, empty_text, 'str'+ user_cmnt, **popt ) else: v = "'" for x in obj: n = ord(x) if n < 256: v += (repr(x) if ver < 3 else ascii(x))[1:-1] elif n < 65536: v += '\\u%04x' % (n,) else: v += '\\U%08x' % (n,) v += "'[:" + str(len(obj)) + ']' print( prefix+ v+ comma, comment, 'str'+ user_cmnt, **popt ) #---------------------------------------------------------------------- # list or tuple: # print one line for each member, in the original order. # append slicing code that shows the length as a full slice #---------------------------------------------------------------------- elif isinstance(obj,(list,tuple)): betype = '[]list' if isinstance(obj,list) else '()tuple' if len( obj ) == 0: print( prefix+ betype[:2]+ comma, comment, empty_text, betype[2:], user_cmnt, **popt ) else: print( prefix+ betype[0], comment, betype[2:], 'len =', len( obj ), user_cmnt, **popt ) n = 0 for v in obj: print_object( v, indent=prelen, index=n, **opts ) n += 1 print( spaces+ betype[1]+ '[:'+ str(len(obj))+ ']'+ comma, comment, end_of_text, betype[2:], **popt ) #---------------------------------------------------------------------- # bool or NoneType: #---------------------------------------------------------------------- elif isinstance(obj,(bool,NoneType)): t = repr(type(obj)).split(' ')[1][1:-2] print( prefix+ repr(obj)+ comma, comment, t+ user_cmnt, **popt ) #---------------------------------------------------------------------- # unknown or simple object: print it vaguely on one line # the output code cannot be used due to this #---------------------------------------------------------------------- else: t = repr(type(obj)).split(' ')[1][1:-2] print( prefix+ __repr__(obj)+ comma, comment, t+ user_cmnt, **popt ) #---------------------------------------------------------------------- # done #---------------------------------------------------------------------- if flush: file.flush() if close: file.close() return None #---------------------------------------------------------------------- # test the print_object() function #---------------------------------------------------------------------- def test_printobject_module( args ): from copy import deepcopy from subprocess import call print( 'from printobject import print_object' ) d = { 'zero':0, 'one':1, 'two':2, 'three':3, 't':True, 'f':False, 4:'four', 5:'five', 1.0j:(0.0,1.0j), 1.0+1.0j:(1.0,1.0j), } x = [ 'this', 'is', 'a', 'nested', 'list' ] o = [ None, False, True, 0, 2**64, 1.25, 2.5j, 'string one', 'string two', d, x, {}, set([]), [], (), set([0]), ] print_object( o, name='first_list' ) return None #---------------------------------------------------------------------- def main( args ): print( '# BEGIN test of print_object()' ) test_printobject_module( args ) print( '# END test of print_object()' ) return 0 #---------------------------------------------------------------------- if __name__ == '__main__': if version_info.major < 3: BrokenPipeError = IOError try: result=main(argv) stdout.flush() except BrokenPipeError: result=99 except KeyboardInterrupt: print('') result=98 if result is 0 or result is None or result is True: exit(0) if result is 1 or result is False: exit(1) if isinstance(result,str): print(result,file=stderr) exit(2) try: exit(int(result)) except ValueError: print(str(result),file=stderr) exit(3) except TypeError: exit(4) # EOF**ducks**
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.