# Name:		classPyDemo.py
# Author:	Dave Renner		dmrenne@comcast.net
# Date:		08/28/11  2030
# Rev:		09/24/12	1945
# Note:		this is a called module of 'pyDemo.py'
# Note:		'classPyDemo.py' demos more complex exception handling
# 			and Python's implementation of O-O classes, including inheritance,
#			delegation, replacement, and augmentation
#
#
# ############################ BOILERPLATE #########################

# import sys
import pickle

myConfigFile = 'pyDemoConfig.dat'

testing_exceptions = 1

# 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("Now, we are in 'classPyDemo.py'. This will demonstrate\
\\nPython's implementation of Object-Oriented programming,\
\\n classes, and inheritance.\
\\nI will just print the code here and run a couple of functions,\
\\nwhich themselves explain what we're doing...")
printf("")

class Super:
    def myFunc(self):
        printf("We are in the 'myFunc' method of class 'Super'.")
        print("We may be calling this from a derived function.")
        printf("")
    def myDelegate(self):
        printf("We are in the delegate' method of class 'Super'.")
        self.provider_do_stuff()
			
class Inheritor( Super ):
    pass
		
class Replacer( Super ):
    def myFunc(self):
        printf( "We are in the 'myFunc' method of class 'Replacer'.")
        printf("")
        printf("This function overrides 'myFunc' in 'Super'.")
        printf("")

class Extender( Super ):
    def myFunc(self):
        printf("We are in the 'myFunc' method of class 'Extender.'")
        printf("We will now call 'Super.myFunc' to do its thing.")
        printf("")
        Super.myFunc(self)
        printf("")
        printf("We are back in our 'Extender' class code.")
        printf("Here is my Extender code. Right, then.")

			
class Provider( Super ):
    def provider_do_stuff(self):
        printf("")
        printf("")
        printf("")
        printf("Finally, now we are in class 'Provider'")
        printf("")


printf("My calling object is a Provider, a Derived class\
\\nof Super. My called function is 'delegate', provided\
\\nin base class 'Super'\
\\n\
\\n'delegate', in turn, called this function,\
\\n'provider_do_stuff', using 'self' as its caller.\
\\n\
\\n'self' is, of course, me, a Provider object. So, in Python,\
\\nProvider' is the only derived class that must provide\
\\nthis 'do_stuff' function.\
\\n\
\\nThis is not like C++.\
\\n")
printf("")

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

printf("")
printf("Python has no virtual base classes with null functions.\
\\nBut it does have inheritance, where derived classes\
\\ncan use base class methods.\
\\n\
\\nAnd Python base class methods can call, or delegate,\
\\nfunctionality to methods of a derived class,\
\\nusing 'self' as an alias for the calling object.\
\\n\
\\n'self' is sort of like 'this' in C++.")

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

my_inheritor = Inheritor()
printf("")
printf("First, we will create an object of empty class 'Inheritor'")
printf("and call the function, 'myFunc' which is inherited from")
printf("its parent, 'Super'.")
printf("")
my_inheritor.myFunc()

printf("")
printf("Next, we will create a class 'Replacer' and call 'myFunc':")
printf("")
my_replacer = Replacer()
my_replacer.myFunc()

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

printf("")
printf("Now, we will create a class 'Extender' and call 'myFunc':")
printf("")
my_extender = Extender()
my_extender.myFunc()

printf("")
printf("Lastly, we create class 'Provider' and call 'myDelegate:'")
printf("")
my_provider = Provider()
my_provider.myDelegate()

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

class Hell(BaseException):
    pass

def notDead():
    if notDead:
        disposition = 'Dead'
        if disposition != 'not dead':
            printf("")		
            printf("I am doing a simple test, and failing")
            printf("Consequently, I am raising an excepton")
            raise Hell


def myXTest():
    try:
        notDead()
    except Hell:
        printf("Here, I have caught the exception, and I say:")
        printf("I'm not dead!")
    finally:
        printf("I am printing this in the 'finally' clause:")
        printf("See you next Thursday")
        printf("")		
        printf("")		


if testing_exceptions:
#	if interactive == '1':
#		printf("")
#		full_cmd = input_cmd + '("' + continue_cmd + '")'
#		eval(full_cmd)	
	printf("")
	printf("We will demo Python's error handling with these classes:\
\\nclass Hell(BaseException):\
\\n    pass\
\\ndef notDead():\
\\n    if notDead:\
\\n        disposition = 'Dead'\
\\n        if disposition != 'not dead':\
\\n            print 'I am doing a simple test, and failing'\
\\n            print 'Consequently, I am raising an excepton'\
\\n            raise Hell\
\\ndef myXTest():\
\\n    try:\
\\n        notDead()\
\\n    except Hell:\
\\n        print 'Here, I have caught the exception, and I say:'\
\\n        print 'I am not dead!'\
\\n    finally:\
\\n        print ' ' \
\\n        print 'I am printing this in the 'finally' clause:'\
\\n        print 'See you next Thursday') \
\\n        print ' '")
	if interactive == '1':
		# printf("")
		full_cmd = input_cmd + '("' + continue_cmd + '")'
		eval(full_cmd)	

if testing_exceptions:
     myXTest()
        
