# Name:         listPyDemo.py
# Author:	Dave Renner	dmrenne@comcast.net
# Date:		08/28/11	1400
# Rev:		09/26/12	2200
# Note:		this is a called module of 'pyDemo.py'
# 	
# Note:		'listPyDemo.py' demos more complex list and string processing,
#			lambda functions, and the difference between assignment equality
#			and content equality
#
#
import os
import os.path
from types import *

interactive = '0'
myConfigFile = 'pyDemoConfig.dat'
TESTING_TYPE = 0
DEBUG1 = 1

# ########################### BOILERPLATE ###########################
import pickle

# version has been stored in our calling module 'pyDemo.py'
PythonVersFile = 'version.obj'
versfile = open(PythonVersFile, 'rb')
PythonVers = pickle.load(versfile)
versfile.close()

if PythonVers == '30':
    import configparser
    config = configparser.ConfigParser()
    input_cmd = 'input'
else:
    import ConfigParser
    config = ConfigParser.ConfigParser()
    input_cmd = 'raw_input'

config.read(myConfigFile)
interactive = config.get('Mode', 'interactive')
continue_cmd = config.get('Strings', 'continue_cmd')

# easier to just include this boilerplate function into every module 
# than to import it
def printf(arg):
    cmdText = "print "
    arg_nonSlash = arg.strip('\\')
    if PythonVers == '30':
        cmdFull = cmdText + '("' + arg_nonSlash + '")'
    else:
        cmdFull = cmdText + '"' + arg_nonSlash + '"'
    exec( cmdFull )

# ##################################################################################

printf("OK, we are now in 'listPyDemo.py'.\
\\n\
\\nThis little code snippet demonstrates a couple of things:\
\\n1) The Python built-in function 'map',\
\\n2) the 'lambda' expression.\
\\n\
\\nFirst, we create a list of strings.\
\\nThen we use the 'map' function to convert those strings\
\\ninto upper case.\
\\n\
\\n'Map' takes 2 arguments:\
\\n1) a function to be performed on each member of the list\
\\n2)the list itself.\
\\n\
\\nWe can specify the function inline\
\\n(it's a simple operation) by using Python's 'lambda' expression.\
\\n'lambda' creates a function in place.\
\\nThe syntax is 'lambda: anArg: anArg.upper()'\
\\nor something like that. It's quicker than to 'def' a function.\
\\nI know this sounds complicated, so it's best to look at\
\\nthe source, 'pyDemo.py'.\
\\n")

if interactive == '1':
    printf("")
    full_cmd = input_cmd + '("' + continue_cmd + '")'
    eval(full_cmd)	

    printf("")
printf("OK, then, I'll print it out for you.")
printf("")
printf("Here it is:\
\\nmyList = ['u', 'p', 'p', 'e', 'r' ]\
\\nprtlam = list( map(lambda x: x.upper(), myList) )\
\\nstrlam = str(prtlam)\
\\nprintf(prtlam)\
")
myList = ['u', 'p', 'p', 'e', 'r' ]
prtlam = list( map(lambda x: x.upper(), myList) )
printf("And here's the result:")
strlam = str(prtlam)
printf(strlam)

#printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	

printf("")
printf("This was tricky to do, this lambda and printing stuff.\
\\nI invoked Python itself for help by getting the data type\
\\nthat is returned from my lambda statement.\
\\nIt is not intuitive.\
\\n\
\\nYou see, unlike Python 2.6, a 'map' in Python 3.0\
\\nreturns an 'iterative' type\
\\nwhich you really can't do too much with.\
\\nI converted this 'iterative' to a 'list', as you can see,\
\\nsince it came from a list in the first place.\
\\nThen I converted the list to a string, so I could print it.\
\\nPretty cool, that Python will convert a list into a string.")

lamtype = type(prtlam)
strlamtype = str(lamtype)
printf("")
printf(strlamtype)

printf("")
printf("")

if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
	
printf("And now we'll do a bit with strings.\
\\nThis will be one of our strings:\
\\n'I know a dead parrot when I see one,'\
\\nThis will be another:\
\\n' and I'm looking at one right now.'\
\\n\
\\nFirst, we will combine them with a simple plus-sign\
\\noperator. You can't do this in C.")
printf("")
deadString = "I know a dead parrot when I see one,"
lookingString = " and I'm looking at one right now. "
comboString = deadString + lookingString
printf(comboString)

printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
	
printf("Now that we have a full string, let us replace\
\\na substring within it. We will use the string 'replace' method\
\\nto modify this string.\
\\nHere goes.")
printf("")

rep = comboString.replace('parrot', 'slug')
printf(rep)
printf("")
printf("OK, it worked.")
printf("(But hardly a replacement, then.)")
printf("")
printf("")
printf("")
printf("Now, we will just use 'rtrim()' to remove\
\\nthe trailing blank. This may be useful for formatting\
\\nstrings for input to a database loader or something.\
\\nIt will not show up here.")
printf("")
comboString.rstrip()
printf( comboString )
printf("")

printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
printf("Now, still in the module 'listPyDemo.py', we\
\\nwill demonstrate the difference between\
\\nassignment equality and content equality.\
\\n\
\\nAn assignment equality points one object to another,\
\\nso both objects will have the same 'object id',\
\\nwhich is Python's unique identifier of an object.\
\\n\
\\nContent equality means that the contents of two\
\\nobjects are the same.")
printf("")

slug1 = ['I', 'got', 'a', 'slug']
slug2 = ['I', 'got', 'a', 'slug']

printf("We have two lists named 'slug1' and 'slug2', respectively.")
printf("Both contain the same content.")
printf("")
printf("slug2 == slug1. True or false?:")
printf("(Python should print the boolean value, converted to a string).")
printf("")
result = slug1 == slug2
printf(str(result))
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)
	printf("")
	
printf("Yes, Python printed 'True'.")
printf("It is true because the '==' operator tests for equivalence,\
\\nor content equality.\
\\nThis makes sense because if two integers are being tested,\
\\nand '==' is usually used to compare two integers,\
\\nwe won't care about their Python IDs -- they're\
\\nprobably temporary objects anyway.")

printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
	
printf("Now, to test the 'is' operator:")
printf ('slug2 is slug1')
result = slug2 is slug1
printf("")
printf(str(result))
printf("")
printf("It is 'False', because the 'is' operator\
\\ncompares Python IDs.\
\\n\
\\n\
\\nSo now, we'll make a real, physical copy of\
\\na list, NOT by allocating two lists, as we\
\\ndid above, but by using the index notation [:]\
\\non one of the lists to create another.\
\\nIn doing this, we will also create a separate object,\
\\n which will NOT pass the 'is' test.\
\\n\
\\nHere's the syntax:\
\\n	slug2 = slug1[:]\
\\n	result = (slug2 is slug1)\
\\n	str_result = str(result)\
\\n	printf( str_result )")

slug2 = slug1[:]
result = (slug2 is slug1)
str_result = str(result)
printf( str_result )

if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")

printf("Yes. It is false, because they have\
\\ndifferent Python IDs.")
	
printf("Finally, we'll just assign one list to another\
\\nwith the 'equal sign' operator. This will create a reference,\
\\nnot a physical copy, so they will pass the 'is' test\
\\nof their Python IDs")
result = slugAssign = slug1
printf("slugAssign = slug1?")
printf("")
printf(str(result))
print("Yes, jolly good. The assignment passes the 'is' test")

printf("")
printf('BTW, the list contains a delightful set of strings')
printf('which, when concatenated, make the phrase:')
slugString = ''
for slugChar in  slug1:
    slugString += slugChar
    slugString += ' '
printf( slugString )

printf("")
printf("")
printf("Now, to the Ministry of Silly os.Walks.\
\\nos.walk is a function that returns the root\
\\ndirectory and all the subdirectories within it,\
\\nand all the files within each of them.")

#printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
	
#topdir = 'C:\\Users\dave\Documents\aDoc'
topdir = os.getcwd()
for root, dirs, files in os.walk(topdir):
    printf("")
    printf('DIRECTORIES')
    for directory in dirs:
        printf( directory )
        printf("")
        printf( 'FILES' )
        for file in files:
            printf( file )
			
printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
	
printf("Completed this Silly Walk.\
\\nNow to go Marching Up and Down the Square.\
\\n\
\\nJ.K.\
\\n(Just Kidding.)\
\\nThe 'walk' was silly because it didn't give us what we need.\
\\nWe want to process (actually, just print) each subdirectory\
\\nand all the files underneath that subdirectory -- a file tree.\
\\n\
\\nWe will note here that 'os.walk' has been deprecated since I \
\\nwrote this test; it's been replaced by the more useful\
\\n'os.path.walk'.\
\\nIn any case...\
\\nLet's try something else. All right, twits?")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	

printf("")
printf("At this point, I should say that I sometimes have a hard time\
\\nprinting stuff because I'm not sure that what I'm printing\
\\nis printable, like a string.\
\\n.Let's test this with Python's 'type' operator, built-in-function,\
\\nor whatever it is. Here's how:\
\\nfrom types import *\
\\ntopdir = os.getcwd()\
\\nmytdtype = type(topdir)\
\\printf(mytdtype)\
\\n\
\\n\
\\nGood, the top directory returned by the OS is a string,\
\\nso it needs no converstion. Paradoxically, the type returned\
\\nby the call 'type()' is NOT a string, so it must be converted\
\\nin order to print it!")

printf("")
if interactive == '1':
	printf("")
	full_cmd = input_cmd + '("' + continue_cmd + '")'
	eval(full_cmd)	
	printf("")
printf("Another printing wrinkle is that our 'printf()' function\
\\nthat we use for 2.6/3.0 compatibility won't work for printing\
\\\nfilenames, which need to preserve all backslashes.\
\\nWe could fix it to make it more versatile, but it's easier\
\\njust to replace it with code such as the following:\
\\n\
\\n	if PythonVers == '30':\
\\n		print(topdir)\
\\nelse:\
\\n    cmdPrint = 'print'\
\\n    cmdFull = cmdPrint + topdir + 'doublequote'\
\\n    exec( cmdFull )")

printf("")
printf("But all this will be handled in another module, 'dirPyDemo'")
