[SOLVED] data structure python Problem Summary:

$25

File Name: data_structure_python_Problem_Summary:.zip
File Size: 357.96 KB

5/5 - (1 vote)

Problem Summary:
Write a class namedCheckAnnotationthat decorates a function,
such that when the decorated function is called, the decorator class
checks the decorated functions annotation, using the annotation
language described below in detail. We can use this decorator by
writing either
def fparamsannotationresultannotation:
fCheckAnnotationf
or

which is a special Python syntactic form that expands to the former assignment. Thus, when the decorated f is called, Python
calls CheckAnnotations.call in the decorator, which first checks the annotations and raises an exception if it is not met and second computesreturns the decorated function f: the original one written.
This class defines four major attributes:
the checkingon instance name to turn offon annotation checking in all decorated functions; it starts on.
the init method to remember the function being decorated and initialize a perfunction name that helps controls annotation checking; it also starts on: for a function call to check its annotation, both checkingon and its perfunction name must be True: if either is False the annotation is not checked.
the call method that intercepts each call to the decorated function and decides whether to check the annotation, and if so implements annotation checking, both for parameters and returned results, if they are specified; if annotation checking succeeds, this method computesreturns the result of calling the decorated function.
the check method specified in more detail below that does the annotation checking: it either succeeds silently or raises an AssertionError exception with useful information specified in the details below. Note that the unconditional assertion,
CheckAnnotation
def fparamsannotationresultannotation:

assert False, message
is a simple way to raise AssertionError with a message. I wrote many nested helper functions in check, one for each data type annotation that can be checked: e.g., checkdict.
Details
Lets explore the meaning of thecallandcheckmethods in
more detail.
I. The call method intercepts calls to the decorated function; it specifies args and kargs to handle all calls, regardless of their parameter structure. My method was about 40 lines but about 17 lines were commentsblank, and 7 comprise the paramargbinding local function supplied in the download; this function computes an ordereddict of the parameter names each associated to its argument in the order that the parameters are defined in the function.
The call method
o determines whether to check the annotations see above;
if not just call the decorated function and return its
result.
o determines the parameters of the function and the
matching arguments they are bound to.
The paramargbindings function written locally in this method returns an ordered dictionary of parametervalue bindings; ordered means that when iterated, keys always appear in the same order: the order the parameters appear in in the functions definition. It uses the various attributes in
the inspect module to do the job. You might be interested in reading the documentation for
the inspect module: it is quite interesting and many of its powerful features are new to Python. It would be an excellent idea to print this data structure to see what information it accumulates for various annotated function that you test in your script.
o determines the annotations of the parameters by using the annotations attribute of any function object. This name is bound to a dictionary containing as keys every annotated parameter name; the associated value for each parameter name is its annotation. If we defined the

function f using def
fx:int,y,z:int:str its annotations dictio nary is
x: class int, z: class int, return: class str
Notice that parameteryhas no annotation so it does
not appear as a key in this dictionary, and the
keyreturnis associated with the annotation for the
returned value after the.
o If any checked annotations parameters or returned result raise the AssertionError handle it by printing the relevant source lines for the function see
the getsourcelines function in the inspect modules documentation and reraise the exception, skipping the rest of the code in this method.
Checks every parameter that has an annotation
Call the decorated function to compute its
returned result and save it.
Ifreturnis in the dictionary of annotions:
a add the result as the value associated with
the keyreturnin the dictionary of parameter
and argument bindings; b check the annotation
forreturn
o self is an instance of the CheckAnnotation class o param is a string that specifies the name of the
parameter being checked orreturnfor checking the
returned value
o annot is a data structure that specifies the annotation o value is the value of param that the annotation
should be checked against to ensure it is legal
o checkhistory is a string that embodies the history of
checking the annotation for the parameter to here it is
extended by concatenation in each recursive call to
provide context for any annotation violations to be

Return the result.
method has the following header
II. The check
def checkself,param,annot,value,checkhistory:
where

checked later; it is printed after the details of any
annotation violation, to suppy context for the failure.
Each call to check decodes the annot to check, and checks it against the value: checks body is one
big ifelifelse determining which local function to call to check the specific annotation and letting that local function do the real work. Most annotations are checked by calling a function defined locally in check that can use the parameters of check freely, because these functions are defined in checks local scope in fact these local functions are often parameterless: many get all the information they need from checks parameters. The more complicated local functions also call check; so check calls a local function which can call check: this is indirect recursion. My method was about 100 lines: about 13 lines were commentsblank, and 60 more appeared in 5 locally declared functions including one to solve the extra credit str part of this assignment so I had about a dozen lines per local function.
The annotation checking language comprises the following
components for Pythons builtin types. Istronglysuggest
writingtesting each component before moving on to the next:
all are similar and
understandingtestingdebugginglistthe first really
interesting one will supply tremendous insight for writing
all.Write the
the ones shown.
o annot is any type e.g., typeannot is type: fail if value is not an instance of the specified type, with an exception messages matching the following examples. The isinstance function covered in the inheritance lectures generalizes checking the type of an object. Instead of writing typex is someclass we write isinstancex,someclass: it checks whether xs object is constructed from someclass or any base class
required exception messages exactly to match
None: do nothing succeed silently. note
fx:has no annotation to check for its
x, but def fx:None: has an annotation to check for x, but it never fails. None has more interesting uses inside more complicated data types, illustrated below see the last example for list.
o annot is that def parameter

of someclass, which is the correct test to perform here.
For def fx:int: called
as fabc or fxabc the exception message would be:
AssertionError: x failed annotation checkwrong type: valueabc
was type str should be type int
For def fx:list: called as f1,2 the
exception message would be:
AssertionError: x failed annotation checkwrong type: value1, 2
was type set should be type list
All exception messages described in the sections below
follow this same general format, although the more
complicated ones supply extra context via
thecheckhistoryparameter.
o annot is a list not the list class object, but an instance of list: a real list of one or more values; see the examples below where each element in list is an annotation. Fail if
1. valueis not a list
2. annothas just one elementannotation, and any of
the elements in thevaluelist fails the
elementannotation check
3. annothas more than one elementannotation, and
a. theannotandvaluelists have a
different number of elements, or
b. any element in thevaluelist fails its
corresponding elementannotation check
Here are some examples of failures:
4. For def fx:int: called as f1,2 the exception message would be:
5. AssertionError: x failed annotation checkwrong type: value1, 2
was type set should be type list

6. For def fx:int: called
as f1,a the exception message would be:
7. AssertionError: x failed annotation checkwrong type: valuea
8. was type str should be type int list1 check: class int
Note that when each element in the list is tested,
it appends the index it is checking and the
annotation it is checking to
thecheckhistorywhich prints after the actual
annotation that fails: here the line
starting list1 check: : it means the element at index 0 did not fail this annotation but the element at index 1 did.
9. For def fx:int,str: called
as f1 the exception message would be:
10. AssertionError: x failed annotation checkwrong number of elements: value1
annotation had 2 elementsclass int, class str
11. For def fx:int,str: called
as f1,2 the exception message would be:
12. AssertionError: x failed annotation checkwrong type: value2
13. was type int should be type str list1 check: class str
Note that the annotation def fx:list: and the annotation def fx:None: have the same meaning but the former is faster to check: the first checks only that x is an instance of list; the second checks that x is an instance of list and then checks each of its values agains the annotation None, which according to that rules annotation does not checking and never fails so really the checks are the same.
Likewise note that for def fx:int,None: called as f1,a no exception is raised, because the annotation for the list element at index 1 is None, which according to that rules annotation does no

checking of the lists value at index1and never
fails.
Note also that for def fx:str: called
as fa,b,c,d no exception is raised, because the annotation says x is a list containing lists that contain only strings. The code to check list annotations will indirectly call itself recursively in the process of checking this annotation. Think about this now, when there are few data types being processed; it will be natural to perform other recursive annotation checks in the check method. In fact, spend a good amount of time simplifying the local function that performs this check, because most of the other annotations listed below look very similar.
Finally, note if we called fa,1,c,d the exception message would be
AssertionError: x failed annotation checkwrong type: value1
was type int should be type str list0 check: class str list1 check: class str
which indicates that the annotation oflist0was
being checked when the annotation forlist1was
being checked each of its values should be
alistofstr, when Python found a nonstring that
violated the annotation.
o annot is a tuple not the tuple class object, but an instance of tuple: a real tuple of values, where each element in annot is an annotation.
Structurally, checking tuples is equivalent to checking
lists all 3 rules apply. In fact, I parameterized the
local function that I originally wrote for checking
lists to work for checking tuples as well. Of course,
the error messages should use the
word list and tuple where appropriate. Caution: remember for tuples of one value we must write fx:int,:; notice the comma after int.

o annot is a dict not the dict class object, but an instance of dict: a real dictonary; see the examples below, with exactly one key: both the key and its associated value are each an annotation. Note, this annotation should work for subclases of dict,
e.g., defaultdict. Check it not by typeannot is dict but using the isinstance function covered in the inheritance lectures: isinstanceannot,dict Fail if
0. valueis not adictor a subclass ofdict
1. annothas more than one keyvalue association:
this is actually a badillegal annotation, not a
failed annotation
2. annothas one keyvalue association, and
a. any key in thevaluedictionary fails the
keyannotation check or
b. any value in thevaluedictionary fails
the valueannotation check
Here are some examples of failures:
3. For def fx:str : int: called
as fa,0 the exception message would be:
4. AssertionError: x failed annotation checkwrong type: valuea, 0
was type list should be type dict
5. For def fx:str : int, int : int: called as fa:0 the exception message would be:
6. AssertionError: x annotation inconsistency: dict should have 1 item but had 2
annotationclass str: class int, class int: class int
7. For def fx:str : int: called
as f1:0 the exception message would be:
8. AssertionError: x failed annotation checkwrong type: value1
9. was type int should be type str dict key check: class str
10. For def fx:str : int: called
as fa:b the exception message would be:

11. AssertionError: x failed annotation checkwrong type: valueb
12. was type str should be type int dict value check: class int
Of course, if a dictionary had many keys, it would check
the required annotations for each of its keys and their
associated values.
o annot is a set not the set class object, but an instance of set: a real set of values; see the examples below where its has exactly one value that is an annotation. Fail if
0. valueis not aset
1. annothas more than one value: this is actually a
badillegal annotation, not a failed annotation
2. annothas one value, and any value in
thevalueset fails the valueannotation check
Here are some examples of failures:
3. 4.
5. 6.
7. 8. 9.
For def fx:str: called
as fa,b the exception message would be: AssertionError: x failed annotation checkwrong type: valuea, b
was type list should be type set
For def fx:str,int: called
as fa,1 the exception message would be: AssertionError: x annotation inconsistency: set should have 1 value but had 2
annotationclass str, class int
For def fx:str: called
as fa,1 the exception message would be: AssertionError: x failed annotation checkwrong type: value1
was type int should be type str set value check: class str
o annot
object, but an instance of frozenset: a real frozenset of values where its one value is an annotation.
is a frozenset not the frozenset class

Structurally, checking frozensets are equivalent to
checking sets all 3 rules apply. In fact, I
parameterized the local function that I originally wrote
for checking sets to work for checking frozensets as
well, similarly to the general function I wrote for
checking liststuple. Of course, the error messages
should use the wordsetandfrozensetwhere
appropriate.
o annot is a lambda or any function object that is a predicate with one parameter and returning a value that can be interpreted as a bool. Fail if
0. annothas zeromore than one parameters: this is
actually a badillegal annotation, not a failed
annotation
1. Calling the lambdafunction
onvaluereturnsFalse
2. Calling the lambdafunction onvalueraises an
exception
Note that we can recognize a functionlambda object by calling the inspect modules isfunction predicate; we can determine the number of parameters in a functionlambda object by accessing
its code.covarnames attribute. You might be interested in reading the documentation for
the inspect module: it is quite interesting and many of its powerful features are new to Python.
Here are some examples of failures: in the first two,
the argument fails thelambdadirectly; in the others
the argument is a list on which thelambdais checked
for every value and fails for one.
3. For def fx:lambda x,y : x0: called as f1 the exception message would be:
4. AssertionError: x annotation inconsistency: predicate should have 1 parameter but had 2
predicatefunction lambda at 0x02BDDC90
5. For def fx:lambda x : x0: called as f0 the exception message would be:
6. AssertionError: x failed annotation check: value0

predicatefunction lambda at 0x02BDDC90
7. For def fx:lambda x : x0: called as f1,0 the exception message would be:
8. AssertionError: x failed annotation check: value0
9. predicatefunction lambda at 0x02BDDC90 list1 check: function lambda at 0x02BDDC90
Note that in this example we are checking
thelambdaannotation for every value in
alist, just as the annotationintwould
check that every value in alistwas an instance
of theintclass.
10. For def fx:lambda x : x0: called as f1,a the exception message would be:
11. AssertionError: x annotation predicatefunction lambda at 0x0022C540 raised exception
12. exceptionTypeError:not supported between instances of str and int
list1 check: function lambda at 0x0022C540
Note that for def fx:lambda x : isinstancex,int and x0: called
as f1,a the exception message would be the more reasonable:
AssertionError: x failed annotation check: valuea
predicatefunction lambda at 0x02BDDC90 list1 check: function lambda at 0x02BDDC90
o annot
the extra credit part below if you implemented it. Assume it is an object constructed from a class that supports annotation checking, by that class defining the the checkannotation method. Fail if
0. There is no checkannotation method in the class: e.g., calling
the checkannotation method raises
the AttributeError exception the object was not constructed from a class that supports the
is not any of the above orstr, specified in

annotation checking protocol: this is actually a
badillegal annotation, not a failed annotation
1. calling its checkannotation method fails
2. calling its checkannotation method raises
any other exception
Note that I have written
the CheckAllOK and CheckAnyOK classes that support the annotation checking protocol; check them out.
Here are some examples of failures. The first assumes
theBagclass does not support the annotation checking
protocol; the second assumes it does; the third assumes
it supports the protocol but raises some other exception
notAssertionError.
3.
4.
5. 6.
7. 8. 9.
For def fx:Bagstr: called
as fBaga the exception message would be:
AssertionError: x annotation undecipherable: Bagclass str1
For def fx:Bagstr: called
as fBaga,1 the exception message would be:
AssertionError: x failed annotation checkwrong type: value1
was type int should be type str
Bag
exceptionTypeError:not supported between instances of str and int
Bag value check: function lambda at 0x006482B8
The checkannotation.py module defines
the CheckAllOK and CheckAnyOK classes, which implement the check annotation protocol.
value check: class str
def fx:Baglambda x : x0: called
For
as
be:
AssertionError: x annotation predicatefunction lambda at 0x006482B8 raised exception
fBaga,1 the exception message would

Extra
Note that with the CheckAnyOK class, we can specify that every value in a list must contain a string or integer. So for def fx:CheckAnyOKstr,int: called
as fa,1 there is no exception raised. Likewise with the CheckAllOK class, we can specify that every value in a list must be an integer and must be bigger than 0. So for def fx:CheckAllOKint,lambda x : x
0:called asf1,2there is no
exception raised.
credit: Implement the following annotations as well.
o annot is a str object, which when evaluated using a dictionary in which all the parameters are defined and the returned result is the value of the key return returns a value that can be interpreted as a bool. This specifiction is similar to lambdasfunctions, but more general, because the expressions can name multiple names, not just the parameter. Fail if
0. Evaluating the string returnsFalse
1. Evaluating the string raises an exception
Here are some examples of failures.
2. For def fx,y:yx: called as f0,0 the exception message would be:
3. AssertionError: y failed annotation checkstr predicate: yx
args for evaluation: x0, y0
Notice that with this form of annotation, we can check properties that depend on values of multiple parameters not just type information. The values of all the parameters are included in the error message. Likewise we can check properties that depend on the returned values. For def fx,yreturnx or returny: return xy called as f3, 5 the exception message would be:

AssertionError: return failed annotation checkstr predicate: returnx or returny
args for evaluation: x3, y5, return8
Notice the value ofreturnis listed with all
the parameter values. Of course, such strings are
easier to read than what Python prints for
lambdasfunctions.
4. For def fx:x0: called as fa the exception message would be:
5. AssertionError: x annotation checkstr predicate: x0 raised exception
exceptionTypeError:not supported between instances of str and int
.
A Largish Example: Full Output
When I put the following code in the script before the driver in the checkannotation.py module.
CheckAnnotation
def fx:int: pass
f1,2,3,4,5,a
the result printed was the following , although I edited out
some of the code that Python displays from my program: lines
that start with

CheckAnnotation
def fx:int: pass
Traceback most recent call last:
File C:UsersPattisworkspace33program4checkannotationsolution .py, line 209, in module
f1,2,3,4,5,a

File C:UsersPattisworkspace33program4checkannotationsolution .py, line 183, in call
my call to self.check
File
C:UsersPattisworkspace33program4checkannotationsolution .py, line 138, in check
my call to check a list File
C:UsersPattisworkspace33program4checkannotationsolution .py, line 70, in checksequence
my call to check a value in the list File
C:UsersPattisworkspace33program4checkannotationsolution .py, line 138, in check
my call to check a list File
C:UsersPattisworkspace33program4checkannotationsolution .py, line 70, in checksequence
my call to check a value in the list File
C:UsersPattisworkspace33program4checkannotationsolution .py, line 137, in check
my call to check a type which failed the assertion causing the following exception
AssertionError: x failed annotation checkwrong type: valuea
was type str should be type int list2 check: class int list1 check: class int
Feel free to put the small tests shown in this document or in the bsc.txt file in the same position before the driver to test the annotations as you write them.
Testing
The sections above present various tests for elements of the
annotation language: they are easy to specify because the
parameter annotations involve only the header: the body can
bepass; when checking return annotations, we can put one

return statement in the body of the code, to return a value
that doesdoesnt satisfy the annotation.
I provided an if namemain: section in
the checkannotation.py module. Again, it is easy to test a simple function there by annotating it and then calling it described in the previous section.
I provided code to call driver.driver which can be used to run individual and batchselfcheck, using the file bsc.txt.
Here is an example of running individual tests. After importing and abbreviating the name of
the CheckAnnotation class it defines a simply annotated function, decorates it, and then calls the function with good and bad arguments which in the latter case rasise an exception because of an annotation failure.
Command!: from checkannotation import CheckAnnotation as ca
Commandfrom checkannotation import CheckAnnotation as ca: def fx:int: pass
Commanddef fx:int: pass: fcaf Commandfcaf: f1 Commandf1: fa
Traceback most recent call last:
File C:UsersPattisworkspacecourselibdriver.py, line 225, in driver
execold,local,globl
File string, line 1, in module File
C:UsersPattisworkspace33program4checkannotation.py, line 183, in call
self.checkp,annotp,self.argsp File
C:UsersPattisworkspace33program4checkannotation.py, line 137, in check
n was type typeasstrvalue should be type typeasstrannotncheckhistory
AssertionError: x failed annotation checkwrong type: valuea
was type str should be type int Commandfa:

When runing batchselfcheck, you might want to start by removing all but the earliest test or comment them out withas you start testing your code.
IMPORTANT for running batchselfcheck: To use
the batchselfcheck you must remove the part of
your call method that prints out the source lines when an assertion exception is raised: otherwise Python will raise a strange exception OSError, which
disrupts batchselfcheck. Comment out the following lines so that your code looks like
except AssertionError:
print80
for l in inspect.getsourcelinesself.f0:ignore starting line
printl.rstrip
print80
raise

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] data structure python Problem Summary:
$25