#!/usr/bin/env python3 # -*- coding: utf-8 -*- from __future__ import division from __future__ import print_function from __future__ import with_statement """ file pyutils.py purpose collection of my useful python stuff email 10054452614123394844460370234029112340408691 The intent is that this module works correctly under both Python 2 and Python 3. Please report failures or code improvement to the author. """ __license__ = """ Copyright © 2016, 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 by decoding the number 10054452614123394844460370234029112340408691 (provu igi la numeron al duuma) """ import base64 import codecs import datetime import decimal import fcntl import hashlib import inspect import json import numbers import os import pickle import pwd import random import signal import struct import subprocess import sys import termios import time # assign some shortcuts now = datetime.datetime.now b16decode = base64.b16decode b16encode = base64.b16encode b32decode = base64.b32decode b32encode = base64.b32encode b64decode = base64.b64decode b64encode = base64.b64encode getencoder = codecs.getencoder dec = decimal.Decimal InvalidOperation = decimal.InvalidOperation sha224 = hashlib.sha224 sha256 = hashlib.sha256 sha384 = hashlib.sha384 sha512 = hashlib.sha512 Number = numbers.Number chdir = os.chdir env = os.environ getcwd = os.getcwd getuid = os.getuid link = os.link mkdir = os.mkdir rename = os.rename remove = os.remove rmdir = os.rmdir randint = random.randint SIGKILL = signal.SIGKILL SIGTERM = signal.SIGTERM call = subprocess.call ocall = subprocess.check_output PIPE = subprocess.PIPE Popen = subprocess.Popen argv = sys.argv stderr = sys.stderr stdin = sys.stdin stdout = sys.stdout version = sys.version version_info = sys.version_info sleep = time.sleep timesecs = time.time stformat = '%Y-%m-%d-%H:%M:%S.%f' tfnformat = stformat.replace(':','-').replace('.','-') __y__=('ano','bai','da','ie','ja','jah','jes','kylla','oui','si','sim', 'taip','tak','yes') __n__=('dim','ei','ez','ingen','inno','nao','ne','nee','nei','nein', 'nej','neniu','nie','no','non','nu') __t__=('cierto','egia','ekte','ikke','istina','pravi','rigtigt','sann', 'satt','totta','true','vera','veraj','verdade','veritable', 'vero','vrai','waar','wahr','wier') __f__=('falsa','falsch','false','falsk','falso','faux','lazan', 'rangar','sbagliate','vaara','vals') __yt__=set(__y__+__t__+('j','y','1')) __nf__=set(__n__+__f__+('n','0')) xrangemax = 0x7fffffffffffffff # 9223372036854775807 if version_info[0] < 3: ints = (int,long,) strs = (str,unicode,) strz = (str,unicode,) ### xrange already defined ### long already defined if version_info[0] > 2: ints = (int,) strs = (str,bytes,bytearray,) strz = (str,) xrange = range long = int def get_terminal_geometry(fd=0): """Get current terminal geometry (width,heght) function get_terminal_geometry purpose get terminal geometry (width,heght) """ try: height,width=struct.unpack('4H',fcntl.ioctl(fd, termios.TIOCGWINSZ,struct.pack('4H',0,0,0,0)))[1::-1] except: height,width=None,None if height==None: try: fd = os.open('/dev/tty',os.O_WRONLY) height,width=struct.unpack('4H',fcntl.ioctl(fd, termios.TIOCGWINSZ,struct.pack('4H',0,0,0,0)))[1::-1] os.close(fd) except: height,width=None,None return (width,height) width,height=0,0 get_terminal_geometry(0) def dp(*msg,**opt): """Print for debugging. function dp purpose print for debugging. note if environment variable 'nodebug' is set then no printing will happen. """ if 'nodebug' in os.environ: return 0 opt['file']=stderr rc=print(*msg,**opt) stdout.flush() return rc def pv(*names,**opts): """Print a variable (name and value) function pv purpose print a variable (name and value) """ p = '==>' for x in names: if not isinstance(x,(list,tuple)): x = [ x ] for name in x: name = str(name) l=inspect.currentframe().f_back.f_locals g=inspect.currentframe().f_back.f_globals if name in l: print(p,'local:',name,'=',repr(l[name])) elif name in g: print(p,'global:',name,'=',repr(g[name])) else: print(p,name,'not assigned') return def zz(secs): """sleep for debugging function zz purpose simple sleep note stderr and stdout flushed before sleep to avoid output loss """ import sys,time sys.stderr.flush() sys.stdout.flush() return time.sleep(secs) def ishashable(o): """True or False if an object value is hashable. function ishashable purpose True or False if an object value is hashable """ try: hash(o) return True except TypeError: return False def qhash(o): """Quietly return the hash of an object or False if it cannot be hashed. function qhash purpose quietly return the hash of an object or False note even False is valid for int() """ try: return hash(o) except TypeError: return False def qrepr(*args,**opts): """Quiet version of repr(). function qrepr purpose quiet version of repr() """ try: return repr(*args,**opts) except: return '' def pyconfig(*args,**opts): """Get settings from config file in Python format. function pyconfig arguments not used, must be omitted options dotdir= directory name (dot prefixed) below home home= explicit home directory to use maxsize= maximum file size (default 1048576) name= file name below directories subdir= additional sub-directory below dotdir uid= user id, uses its home directory purpose get settings from config file in python format note a config file in Python format is a Python script that sets a collection of local variables which are used as the settings returned as a dictionary. note this function needs updating to support windows. """ if len(args)>0: m='positional arguments are not used: ' m+=', '.join([repr(a) for a in args]) raise Exception(m) uid=opts.pop('uid',os.getuid()) home=opts.pop('home',pwd.getpwuid(uid).pw_dir) maxsize=int(opts.pop('maxsize',1048576)) if 'path' in opts: p=opts['path'] else: p=home if 'dotdir' in opts: p += '/.' + opts.pop('dotdir') if 'subdir' in opts: p += '/' + opts.pop('subdir') p += '/' + opts.pop('name') if len(opts)>0: m='unknown option' if len(opts)>1: m+='s' m+=': '+', '.join([str(n)+'='+repr(v) for n, v in opts.items()]) raise Exception(m) with open(p) as f: s=f.read(maxsize+1) if len(s)>maxsize: m='config file {} size is larger than {}' raise Exception(m.format(repr(p),repr(maxsize))) c={} exec(s,c) del c['__builtins__'] return c def bytes_as_bytearray(b): """Return a bytes value as type bytearray. function bytes_as_bytearray purpose return a bytes value as type bytearray note this function bypasses all encoding and decoding with the result that byte/character values are unchanged """ return bytearray(b) def bytes_as_str(b): """Return a bytes value as type str. function bytes_as_str purpose return a bytes value as type str note this function bypasses all encoding and decoding with the result that byte/character values are unchanged """ if version_info[0] < 3: return ''.join([chr(ord(c)) for c in b]) else: return ''.join([chr(c) for c in b]) def bytearray_as_bytes(b): """Return a bytearray value as type bytes. function bytearray_as_bytes purpose return a bytearray value as type bytes note this function bypasses all encoding and decoding with the result that byte/character values are unchanged """ if version_info[0] < 3: return ''.join([chr(c) for c in b]) else: return bytes(b) def bytearray_as_str(b): """Return a bytearray value as type str. function bytearray_as_str purpose return a bytearray value as type str note this function bypasses all encoding and decoding with the result that byte/character values are unchanged """ return ''.join([chr(c) for c in b]) def str_as_bytes(b): """Return a str value as type bytes (str in python2). function str_as_bytes purpose return a str value as type bytes (str in python2) note this function bypasses all encoding and decoding with the result that byte/character values are unchanged """ if version_info[0] < 3: return bytes(b) else: z=[hex(ord(c)).replace('x','0')[-2:] for c in b] return bytes.fromhex(''.join(z)) def str_as_bytearray(b): """Return a str value as type bytearray. function str_as_bytearray purpose return a str value as type bytearray note this function bypasses all encoding and decoding with the result that byte/character values are unchanged """ if version_info[0] < 3: return bytearray(chr(0)[0:0].join([chr(ord(c)) for c in b])) else: z = [hex(ord(c)).replace('x','0')[-2:] for c in b] return bytearray.fromhex(''.join(z)) def hexify(o): """Convert strings,byte,ints,longs tohex function hexify purpose convert strings,byte,ints,longs to hex """ if isinstance(o,(bytes,bytearray,memoryview)): return o.hex() if isinstance(o,strz): return ''.join([hex(ord(c)) for c in o]) if isinstance(o,ints): return hex(o) return hexify(repr(o)) _rot13 = getencoder('rot-13') def rot13(x): """Do rot13 conversion in a simple API way function rot13 purpose do rot13 conversion in a simple API way """ return _rot13(x)[0] def chunks(s,l): """Split a sequence into fixed size chunks function chunks purpose split a sequence into fixed size chunks note the last chunk is often shorter arguments 1 sequence to be split 2 length of each chunk (except last) thanks j.crater,wavic,Mekire (python-forum.io) """ return [s] if l<1 else (s[0+i:l+i] for i in range(0,len(s),l)) def timeyears(): """Return the current time scaled in average years (365.2425 days) of the proleptic Gregorian calendar function timeyears purpose return the current time scaled in average years (365.2425 days) of the proleptic Gregorian calendar """ return timesecs()/31556952.0 def timemonths(): """Return the current time scaled in average months (30.436875 days) of the proleptic Gregorian calendar function timemonths purpose return the current time scaled in average months (30.436875 days) of the proleptic Gregorian calendar """ return timesecs()/2629746.0 def timeweeks(): """Return the current time scaled in weeks function timeweeks purpose return the current time scaled in weeks """ return timesecs()/604800.0 def timedays(): """Return the current time scaled in days function timedays purpose return the current time scaled in days """ return timesecs()/86400.0 def timehours(): """Return the current time scaled in hours function timehours purpose return the current time scaled in hours """ return timesecs()/3600.0 def timemins(): """Return the current time scaled in minutes function timemins purpose return the current time scaled in minutes """ return timesecs()/60.0 def timemsecs(): """Return the current time scaled in milliseconds function timemsecs purpose return the current time scaled in milliseconds """ return timesecs()*1000.0 def timeusecs(): """Return the current time scaled in microseconds function timeusecs purpose return the current time scaled in microseconds """ return timesecs()*1000000.0 def timensecs(): """Return the current time scaled in nanoseconds function timensecs purpose return the current time scaled in nanoseconds """ return timesecs()*1000000000.0 def fint(x): """Convert x to an int only if x is a float with an int value function fint purpose convert x to an int only if x is a float with an int value """ if isinstance(x,float): if x.is_integer(): return int(x) return x def tfn(): """Return a timestamp string for a filename function tfn purpose return a timestamp string for a filename """ return now().strftime(tfnformat) def var(name,default): """Get a named value from a file or the default. function var purpose get a named value from a file or the default """ try: with open('.'+name) as f: return f.read() except IOError: pass return default def xprint(*msg,**opt): """Print, avoiding exceptions such as broken pipes. function xprint purpose print, avoiding exceptions such as broken pipes. also extends file= option to support str and int values file=str is a file name to be opened, printed to, then closed file=int is a file descriptor to be used """ doclose = False if 'file' in opt: ofile = opt['file'] try: if isinstance(ofile,strs): ofile = open(ofile,'w') doclose = True if isinstance(ofile,int) and ofile > 0: ofile = os.fdopen(ofile,'w') except (BrokenPipeError,IOError,KeyboardInterrupt): return opt['file'] = ofile try: otime = opt.pop('time',False) if otime: r = print(now().strftime(stformat),*msg,**opt) else: r = print(*msg,**opt) except (BrokenPipeError,IOError,KeyboardInterrupt): r = None if doclose: try: ofile.close() except (BrokenPipeError,IOError,KeyboardInterrupt): pass return r def tprint(*msg,**opt): """Like xprint but defaults to time=True function tprint purpose like xprint but defaults to time=True """ opt['time'] = opt.pop('time',True) return xprint(*msg,**opt) def eprint(*msg,**opt): """Like xprint() but defaults to file=stderr. function eprint purpose like xprint() but defaults to file=stderr. """ opt['file'] = opt.pop('file',sys.stderr) return xprint(*msg,**opt) def teprint(*msg,**opt): """Like tprint() but defaults file= to stderr. function teprint purpose like eprint() but defaults to time=True """ opt['time'] = opt.pop('time',True) return eprint(*msg,**opt) def vcall(*a,**aa): """Execute the given command after outputting the command. function vcall purpose execute the given command after outputting the command to stdout or where specified with cmdfile= or cmdfilename= """ doclose = None if len(a) < 1: return -1 if 'cmdfilename' in aa and isinstance(aa['cmdfilename'],strz): try: cmdfile = open(aa['cmdfilename'],'a') doclose = cmdfile aa['cmdfile'] = cmdfile except IOError: pass aa.discard('cmdfilename') if 'cmdfile' in aa: xprint(repr(a[0]),file=aa['cmdfile']) if doclose != None: doclose.close() else: xprint(repr(a[0])) stdout.flush() return call(*a,**aa) def vecall(*a,**aa): """Like vcall but defaults output to stderr. function vecall purpose like vcall but defaults output to stderr. """ doclose = None if len(a) < 1: return -1 if 'cmdfilename' in aa and isinstance(aa['cmdfilename'],strz): try: cmdfile = open(aa['cmdfilename'],'a') doclose = cmdfile aa['cmdfile'] = cmdfile except IOError: pass aa.discard('cmdfilename') if 'cmdfile' in aa: eprint(repr(a[0]),file=aa['cmdfile']) if doclose != None: doclose.close() else: eprint(repr(a[0])) stderr.flush() return call(*a,**aa) def ecall(args,**opt): """Like vcall() but defaults to file=sys.stderr function ecall purpose like vcall() but defaults to file=sys.stderr """ if 'file' not in opt and 'filename' not in opt: opt['file'] = stderr return vcall(args,**opt) def bcall(s,a): """Execute the given command in a named screen background session. function bcall purpose execute the given command in a named screen background session note due to a misfeature of screen the process started this way cannot be SIGSTOPped (SCREEN does SIGCONT) """ if len(a) < 1: return -1 if 'DISPLAY' in os.environ: d = os.environ['DISPLAY'] else: d = '' return 0 if 0 == call(['/usr/bin/env','DISPLAY='+d, 'SESSION_NAME='+s,'/usr/bin/screen','-S',s, '-dm']+a) else -2 def acall(*args,**opts): """Like call but all the positional arguments form the command. function acall purpose like call but all the positional arguments form the command """ if len(args) < 1: return -1 return call(args,**opts) def xcall(args,**opt): """Like call but executes in the current process. function xcall purpose like call but executes in the current process replacing the python interpreter running this code and its caller. """ if len(args) < 1: return -1 return os.execvp(args[0],args) def xacall(*args,**opts): """Like acall but executes in the current process. function xacall purpose like acall but executes in the current process replacing the python interpreter running this code and its caller. """ if len(args) < 1: return -1 return os.execvp(args[0],args) def q_chdir(*a): """Do chdir() without raising an exception function q_chdir purpose do chdir() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.chdir(*a) except OSError: pass return result cd = q_chdir def q_mkdir(*a): """Do mkdir() without raising an exception function q_mkdir purpose do mkdir() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.mkdir(*a) except OSError: pass return result def q_link(*a): """Do link() without raising an exception function q_link purpose do link() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.link(*a) except OSError: pass return result def q_symlink(*a): """Do symlink() without raising an exception function q_symlink purpose do symlink() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.symlink(*a) except OSError: pass return result def q_rename(*a): """Do rename() without raising an exception function q_rename purpose do rename() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.rename(*a) except OSError: pass return result def q_remove(*a): """Do remove() without raising an exception function q_remove purpose do remove() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.remove(*a) except OSError: pass return result rm = q_remove def q_rmdir(*a): """Do rmdir() without raising an exception function q_rmdir purpose do rmdir() without raising an exception usage this is convenient for use cases where an error can be ignored """ result = None try: result = os.rmdir(*a) except OSError: pass return result def b16to32(x): """Convert base 16 encoding to base 32 encoding function b16to32 purpose convert base 16 encoding to base 32 encoding """ return b32encode(b16decode(x.upper())).decode('ascii') def b16to64(x,*a): """convert base 16 encoding to base 64 encoding function b16to64 purpose convert base 16 encoding to base 64 encoding """ return b64encode(b16decode(x.upper()),*a).decode('ascii') def b32to16(x): """convert base 32 encoding to base 16 encoding function b32to16 purpose convert base 32 encoding to base 16 encoding """ return b16encode(b32decode(x)).decode('ascii').lower() def b32to64(x,*a): """convert base 32 encoding to base 64 encoding function b32to64 purpose convert base 32 encoding to base 64 encoding """ return b64encode(b32decode(x),*a).decode('ascii') def b64to16(x,*a): """convert base 64 encoding to base 16 encoding function b64to16 purpose convert base 64 encoding to base 16 encoding """ return b16encode(b64decode(x,*a)).decode('ascii').lower() def b64to32(x,*a): """convert base 64 encoding to base 32 encoding function b64to32 purpose convert base 64 encoding to base 32 encoding """ return b32encode(b64decode(x,*a)).decode('ascii') def lcset(s): """make a copy set with strings converted to lower case function lcset purpose make a copy set with strings converted to lower case """ new = set() for x in s: if isinstance(x,strs): new += x.lower() else: new += x return new def ucset(s): """make a copy set with strings converted to upper case function ucset purpose make a copy set with strings converted to upper case """ new = set() for x in s: if isinstance(x,strs): new += x.upper() else: new += x return new def mcenv(name): """Mixed case environment lookup (UPPER CASE PREVAILS) function mcenv purpose mixed case environment lookup (UPPER CASE PREVAILS) """ if name.upper() in env: return env[ name.upper() ] if name.lower() in env: return env[ name.lower() ] if name in env: return env[ name ] return None def valid_decimal(decarg): """non-exception test if given value can be decimal.Decimal (dec) function valid_decimal purpose non-exception test if given value can be decimal.Decimal (dec) """ try: r = dec(decarg) except InvalidOperation: r = None return r def unmod(n,m): """Return the remainder after subtracting the modulus function unmod purpose return the remainder after subtracting the modulus note if a list or tuple of numbers is given, return in kind arguments 1 (num) number 2 (num) modulus returns (num) number - (number % modulus) example unmod(456789,1000) -> 456000 usage unmod(256,15) -> 240 unmod(seconds,3600) -> start of this hour in seconds unmod(seconds,86400) -> start of this day in seconds unmod(minutes,1440) -> start of this day in minutes """ if not isinstance(m,Number): raise TypeError('Not a number passed to unmod() arg2: ' +\ '%s (modulus)' % repr(m)) if isinstance(n,list): return [unmod(x,m) for x in n] if isinstance(n,set): return set([unmod(x,m) for x in n]) if isinstance(n,tuple): return tuple([unmod(x,m) for x in n]) if not isinstance(n,Number): raise TypeError('Not a number passed to unmod() arg1: ' +\ '%s (value)' % repr(n)) if m == 0: raise ValueError('Zero passed to unmod() arg2 (modulus)') if m < 0: raise ValueError('Negative value passed to unmod() arg2: ' +\ '%s (modulus)' % repr(m)) return n - (n % m) def sleep_to_interval(i): """sleep to the next interval boundary function sleep_to_interval purpose sleep to the next interval boundary """ stdout.flush() return sleep(i-timesecs()%i) def scale(n,o,value): """Change the scale of given number(s) function scale purpose change the scale of given number(s) arguments 1 (num) the new scale (from,to) 2 (num) the old scale (from,to) 3 (num or list/set/tuple of nums) value(s) to be rescaled returns (like arg 5) rescaled value(s) or None """ if isinstance(value,list): return [scale(n,o,x) for x in value] elif isinstance(value,set): return set([scale(n,o,x) for x in value]) elif isinstance(value,tuple): return tuple([scale(n,o,x) for x in value]) d = o[1] - o[0] return ((n[1] - n[0]) * (value - o[0]) + (n[0] * d)) / d def plural(value,one='',not_one='s'): """ function plural purpose Syntactic sugar to return 's' for plural cases else '' or allow substituting other strings. examples print('I see %d thing%s here'%(n,plural(n))) print('il y a %d chose%s ici'%(n,plural(n))) print('Det er %d element%s her'%(n,plural(n,'','er'))) print('There %s %d thing%s here'%(plural(n,'is','are'), n,plural(n))) """ return one if value==1 else not_one def yes_or_no(x,no=False,yes=True,unknown=None): """Determine if a given string means yes/true or no/false function yes_or_no aliases oui_ou_non,ja_oder_nein,ja_of_nee,ja_eller_nej, ja_eller_nei purpose determine if a given string means yes/true or no/false arguments 1: the string or value to check no= alternate value to return for no/false yes= alternate value to return for yes/true unknown= alternate value to return for unknown returns False or the value of no= if string/value indicates no/false True or the value of yes= if string/value indicates yes/true None or the value of unknwon= if string/value cannot be determined note Only a few European languages are represented here. """ if isinstance(x,strs): if str(x).lower() in __nf__: return no elif str(x).lower() in __yt__: return yes elif isinstance(x,Number): if x: return yes else: return no return unknown oui_ou_non = yes_or_no ja_oder_nein = yes_or_no ja_of_nee = yes_or_no ja_eller_nej = yes_or_no ja_eller_nei = yes_or_no def test_pyutils(args): """ function test_pyutils purpose perform tests of functions in this module with results output to stdout """ alpha = '0123456789abcdefghijklmnopqrstuvwxyz' +\ 'abcdefghijklmnopqrstuvwxyz'.upper() tprint('Python',version) tprint('\nTesting scale') for c in (-40,0,10,15.20,25,100): f = scale((32,212),(0,100),c) c = scale((0,100),(32,212),f) tprint(str(f)+'F','==',str(c)+'C') tprint('\nTesting plural') for n in (1,2,3): xprint() tprint('Il y a %d chose%s ici'%(n,plural(n))) tprint('Det er %d element%s her'%(n,plural(n,'','er'))) tprint('There %s %d thing%s here'%(plural(n,'is','are'),n, plural(n))) tprint('\nTesting oui_ou_non') for f in ('oui','non','yes','no','True','False','None','unknown', True,False,None,-1,0,1,2): if oui_ou_non(f): e = True else: e = False tprint('for',repr(f),'the result is',repr(e)) xprint() for x in range(0,12): print(x,repr(list(chunks(alpha,x)))) for x in (18,36,99,0,-1,-2,-3): print(x,repr(list(chunks(alpha,x)))) xprint() sleep_to_interval(2.0) tprint('time is',repr(timeyears()),'years') sleep_to_interval(2.0) tprint('time is',repr(timemonths()),'months') sleep_to_interval(2.0) tprint('time is',repr(timeweeks()),'weeks') sleep_to_interval(2.0) tprint('time is',repr(timedays()),'days') sleep_to_interval(2.0) tprint('time is',repr(timehours()),'hours') sleep_to_interval(2.0) tprint('time is',repr(timemins()),'minutes') sleep_to_interval(2.0) tprint('time is',repr(timesecs()),'seconds') sleep_to_interval(2.0) tprint('time is',repr(timemsecs()),'milliseconds') sleep_to_interval(2.0) tprint('time is',repr(timeusecs()),'microseconds') sleep_to_interval(2.0) tprint('time is',repr(timensecs()),'nanoseconds') xprint() eprint('Python',version.split('\n')[0]) eprint("str_as_bytes(u'foobar')",'=', repr(str_as_bytes(u'foobar'))) eprint("str_as_bytearray(u'foobar')",'=', repr(str_as_bytearray(u'foobar'))) eprint("str_as_bytes('foobar')",'=', repr(str_as_bytes('foobar'))) eprint("str_as_bytearray('foobar')",'=', repr(str_as_bytearray('foobar'))) eprint("bytes_as_str(b'foobar')",'=', repr(bytes_as_str(b'foobar'))) eprint("bytes_as_bytearray(b'foobar')",'=', repr(bytes_as_bytearray(b'foobar'))) ba = bytearray(b'foobar') eprint("bytearray_as_str(bytearray(b'foobar'))",'=', repr(bytearray_as_str(ba))) eprint("bytearray_as_bytes(bytearray(b'foobar'))",'=', repr(bytearray_as_bytes(ba))) xprint('DONE',time=True) return 0 def main(args): """Call test_pyutils(args) when main(args) is called.""" return test_pyutils(args) if __name__ == '__main__': try: result=main(sys.argv) sys.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=sys.stderr) exit(2) try: exit(int(result)) except ValueError: print(str(result),file=sys.stderr) exit(3) except TypeError: exit(4) # EOF