View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide

Adam Wilson

Turnin Testing

Currently Working On:


Finished Working On:


Important changes:



JES Observations & Notes:

JESProgram-
"checkForSave(self):
"pass
What does this do?

It looks like JESProgram uses the Interpreter, an Exception Record, and Tabnanny to check code before it's loaded. The it tells the interpreter to load it. Why not have the interpreter take care of that, or better yet have something take care of it for the interpreter inside the interpreter. It would clean up JESProgram, and maybe while moving stuff around, we can see ways to cleans it up.

Is there a reason that the Interpreter reads code from the file instead of the Buffer when it's loaded? "Save it, load it" was somewhat annoying for making little changes. Could we just run the buffer into the Interpreter instead of the file?

After the JESThread is launched when running code (loading code runs also), threadCleanup() is called. It looks like the occasional minutes-long pause might be coming from this method.

The CommandWindow looks built from the ground up. Is there any way we can just pipe the normal jython interpereter through that window. I know that the error messages need to be changed, and some parts of the environment need to be changed, but can we intercept that instead of doing everything? I haven't completely gone through JESCommandWindow.py, so if I'm off base tell me.

JESCommandWindow: The contents of the window is a document where the program explicitly controls the cursor and input/output. It seems to work well, but can we improve it?

Why do we have both showText and showError? They do the exact same thing.

Look in the comments: If they're along the lines of "This is a hack" or "this needs to be fixed" we should look at it.

JESEditorDocument is the class where all the document editing takes place. It's also where al the highlighting takes place.

We might want to think about making keywordHighlightEvent(in JESEditorDocument) as lean and mean as possible, since it get called every time text is inserted or removed.

JESUI is HUGE. Is there any way we could break it up a little more?

In the constants, we might want to make the initial mail server smtp.mail.gatech.edu, to reduce confusion. OR, better yet, we could come up with a better turnin system.

I would just like to thank Jason, Claire, David, and Josh for their comments. The fact that they have almost as many comments as code cuts about 50% of the digestion time out. They are even good WITHOUT syntax highlighting. Mad props guys, mad props.

Save-Load solutions:
I'm leaning towards the last two, but haven't decided yet. If we could keep track of all the def statements and load them dynamically as code is run in the command area, we could do away with the load button altogether. Of course, that's the most difficult thing for the developers we could possibly do, but it would probably be the best from the user's perspective.

Problems with emailing assignments. It looks like off-campus emails are the worst because of the myriad SMTP capabilities. MSN seems to be the worst. Here's what I'm thinking about:

New Turnin Procedure Proposal:
The old turnin procedure generated a mail message and sent it to the TA via SMTP. There were many problems with this:
The new procedure takes advantage of the security and upload capabilities of the coweb. A new swiki will be created called cs1315turnin. The security settings will be such that you can upload to a page without authentication, but must have authentication to view an attachment. The 2340turnin coweb uses a similar security scheme for their turnins.

The front page of the coweb will have a list of the TAs for the class. Each TA's name will be a link to another coweb page. This coweb page will have a list of all the assignments for the semester. Each assignment will be a link to that particular TA's assignment upload page.

The turnin procedure will automated through JES. JES will read a descriptions file on the turnin coweb to see where each student should upload each assignment. The turnin definitions page will be formatted like this:
#BEGIN_TA_ASSIGNMENTS
STUDENT_GT_NUM|TA_GT_NUM
...
#BEGIN_TURNIN_LOCATIONS
TA_GT_NUM|ASSIGNMENT_NAME|TARGET_COWEB_ADDRESS

JES will read the definitions file from the server and decide where to upload the assignment. Once it has the appropriate URL, it will take the generated zip file and form an HTTP POST message to the URLs '.attach' script with the fields specific='true' and reference='true'. This will attach the file and create a reference on the page to it. The TA can then go to the page, and using the authentication download all the zips for the assignment.

The only drawback to this method is that the TAs must download all their student's submissions individually. This, however is no different from having to remove and unzip email attachments.
Here's some good code for sending POST messages:
import httplib, mimetypes

#Written by: Wade Leftwich
#Date: 8/23/2002
#URL: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
def post_multipart(host, selector, fields, files):
    #Post fields and files to an http host as multipart/form-data.
    #fields is a sequence of (name, value) elements for regular form fields.
    #files is a sequence of (name, filename, value) elements for data to be uploaded as files
    #Return the server's response page.
    content_type, body = encode_multipart_formdata(fields, files)
    h = httplib.HTTPConnection(host, 8888)
    h.putrequest('POST', selector)
    h.putheader('content-type', content_type)
    h.putheader('content-length', str(len(body)))
    h.endheaders()
    h.send(body)
    response = h.getresponse()
    return response

def encode_multipart_formdata(fields, files):
    #fields is a sequence of (name, value) elements for regular form fields.
    #files is a sequence of (name, filename, value) elements for data to be uploaded as files
    #Return (content_type, body) ready for httplib.HTTP instance
    BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
    CRLF = '\r\n'
    L = []
    for (key, value) in fields:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"' % key)
        L.append('')
        L.append(value)
    for (key, filename, value) in files:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        L.append('Content-Type: %s' % get_content_type(filename))
        L.append('')
        L.append(value)
    L.append('--' + BOUNDARY + '--')
    L.append('')
    body = CRLF.join(L)
    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    return content_type, body

def get_content_type(filename):
    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

>>> f = open("/Users/awilson/Desktop/jesbuild-5-20.zip", "r+b")
>>> zip = f.read()
>>> files = [["filestuff", "jesbuild-5-20.zip", zip]]
>>> post_multipart(host, selector, fields, files)
<httplib.HTTPResponse instance at 1589936>
>>> host
'127.0.0.1'
>>> selector
'/Test/1.attach'
>>> fields
[['specific', 'true'], ['reference', 'true']]


Adam Wilson
awilson@cc.gatech.edu
http://www.cc.gatech.edu/~awilson
test.zip

Links to this Page