Adam Wilson
Turnin Testing
Currently Working On:
- 6/30: User testing. These are some of the things I'd like to look at in user testing.
- Usage of the debugger:
- do they use it to completion?
- do the step, go slowly, or fast.
- do they watch variables or execution
- do they expect it to do something different
- do they try to change the program while the debugger is running?
- do the want to, would it seem natural?
- do they watch live execution, or do they go back and look at the history of execution?
- Blocks:
- with highlighting on, do they more easily viualize blocks
- with the monospaced font, is it just as easy without the boxes?
- are they visually distracting?
- are they interpreting the boxes correctly, i.e. thread of execution?
- is the color good?
- New help features:
- when informed about the highlighting help, do they use it?
- if they use it, are the examples and help information good?
- when do they use it, if they do?
- Keyboard shortcuts:
- Loaded/Unloaded visual cues;
- does this prevent problems with forgetting to load code?
- how would they like to be informed that the code has not been loaded?
- Using strings with highlighting;
- do they understand better how string concatenation works?
- is it more easy to visualize the difference between "..." and '...'?
- can they better imbed quotes into strings, i.e. "..'.." and '.."..'?
- General usage:
- is anything not working correctly or as expectected?
- did we make a change that they don't like?
- 6/27: New path features proposal in JES:
- setPath(string): sets the current working directory
- once the path has been set, any file in that directory can be referenced by just its basename.
- Jython cannot change the current working directory, unlike Python. To make this work, every time a path is used, we need to check to see if it is just a base name, or a full path. If it's just a base name, we append the string set in setPath. If it's a full path, we just use the full path without appending anything.
- Is this what we want to do?
- 6/23 ^M^M bugs. mmm m&ms
- 6/19 Cleaning up JES for a release. Makiing sure everything still works right.
- Contextual Help popups.
- 6/4 - Got plain text working, now we'll see if I can spruce it up by rendering html.
- 6/5 - Got html to work... here's a screenshot.
- 8/19 - working on cleaning them up, grammar, better examples, and better explanations. You know, when I get bored with coding.
- 6/11: Block highlighting - Got Toby's "where the cursor is" highlight idea to work. It's really cool. Basically, JES draw a block around the lowest-level block you're working on. It removes spacing ambiguity, but doesn't clutter up the work area. Here's a screenshot: 'Hyow.
- 6/16: Working on the gutter now. I'm thinking about making it customizable ( however many features the user wants). There are some very cool screenshots on the JEdit page of their editor that's got a good gutter: jedit-snap-10.png, jedit-snap-11.png, and jedit-snap-17.png I like the system in the first one with the hanging triangles for level indentation and the drop line on the current block.
Finished Working On:
- 5/14: Fixed the getMediaPath & setMediaFolder discrepancy. Now there is getMediaPath() and setMediaPath() and getMediaFolder() and setMediaFolder(). Both the set interchange with each other. Old stuff will still work, but new stuff can be parallel in nomenclature.
- 5/14: Fixed makeColor pickiness. It will take crap from anybody.
- 5/14: A script to automate regression testing
- 5/15: Yellow error highlighting thing. Still need to evaluate design.
- 5/16: Save-Load issue. The load button will be green while the interpreter is current with the editor. When the editor document is changed, the button turns red until the document is reloaded successfully. If you try to run a command while the button is red, it'll spit "WARNING: Current code has not been loaded." at you. Not completely fool-proof, but it's obvious now.
- 5/28: Done with new turnin scheme. The description is down the page somewhere...
- 5/29: Resizing entire window should resize editor and not command area.
- 6/02; JESEditorDocument.py supports comment and string highlighting. It works, comments inside strings are still strings, and strings inside comments are still comments. it even recognizes single-quote vs. double-quote strings. The problem is that it slows it down. Not noticably when you're editing, but very noticable when you load a very large file (100's of lines). To get it to run, you need to grab the new JESConstants.py from the repository and get this new .py. I'm not putting it in the repository yet, because we might not want to trade off the speed. Oh, here's a screen shot. Right now I'm seeing if it can be optimized more... for the speed.
- After looking more carefully at the way things work, I'm thinking it might be worth it to do all the highlighting in java. Since it's not one of the critical things right now, I'm going to put the highlighting on hold until we get JES out the door for summer schools.
- 5/29: I finished the turnin stuff, so I need another large project. I'm looking at improving the speed of the highlighting. To do this I'd definitely have to do it in Java. A document listener that reeveluates changes would do the trick. Also, I just found that Java 1.4 supports regular expressions. That will make the highlighting MUCH easier. Now the question is, do I want to make a highly-extensible highlighter that just has a set of regexes and colors passed in? That would be uber-cool, but probably overkill.
- 5/30: Decided to use regex's instead of just searching. I hope it's faster.
- 6/24 Making the Open/save dialog go to the last place you used it, instead of the same place all the time.
- 6/27 Making the gutter and block highlighting optional in JES
Important changes:
- Add this to the documentation: setMediaPath() has been added with the functionality of setMediaFolder() and getMediaFolder() has been added with the same functionality as getMediaPath()
- Error Highlighting - The problem was that the highlighting got a start position and then an offset. The highlighting was undone after a change had been made, which could have changed the real end of the line offset. Unfortunately the error offset did not reflect that. I changed it to remove the highlighting after a change is made, but before it is reflected in the document.
- We were tossing around the idea of undoing the highlighting on a load. This change doesn't do that, but we still might want to consider it.
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.
- UPDATE: (5/13/03) Okay, I was off base. It's not as complicated as I thought, and it's actually done very well. I'm impressed that it has the multi-line block functionality!
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.
- showErrorLine(self, lineNumber) sets a character attribute for the entire line. Maybe we should just set a flag for error highlighting, and then every time the document is changed, we remove all error highlighting?
- Better yet, maybe the debugger people could find a way to get the function call or variable that caused the error. Maybe we coud just invoke a debugger function.
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:
- Make the load button save the contents to a temporary file, or not even save them, just run the conents to the interpreter.
- PROBLEMS: Still have to save AND load, and can save but forget to load.
- Give a visual cue that the contents of the editor window are not current with the interpreter.
- PROBLEMS: Still can accidentally use old, previously loaded code
- Whenever a command is given in the command area, load the contents of the of the editor to the interpreter.
- PROBLEMS: The user might not mean to use code from the editor
- The code in the editor might be bad, and it would spit out an error.
- SOLUTIONS: keeps track of defs in the editor, and only load the code from the editor when one of those is referenced.
- Make the code automatically load on save.
- PROBLEMS: might want to save bad code if you're in the middle of working on something
- SOLUTIONS: still save the file, but give a notice saying that the code is bad and it hasn't been loaded.
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:
- Adding user/pass capabilities. This might enable more servers to be used.
- Some servers look at the from domain, and block any not from their own domain. So, sending mail through MSN with the from field saying prism won't work.
- Plus, MSN uses SPA, which I'm sure we can't get a license for.
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:
- Verification. The only way that a student could be sure if their assignment was successfully submitted was by requesting a response from their TA. This is not dependable, and places a undue burden upon the TAs
- Reliablity. Only on campus mailing were guaranteed to work. Students who were off campus had to deal with their ISPs SMTP servers, some of which would not work with the turnin mail format.
- Akwardness. TAs got their student's assignments via email, which is used often for personal work. This cluttered up their inboxes, and got their attention every time a student submitted an assignment.
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
- JES Sum03 Bug List last edited on 24 June 2003 at 11:37 am by anemone.cc.gatech.edu
- Sum03 JES Development last edited on 25 October 2003 at 5:41 pm by OL117-12.fibertel.com.ar
- JES Sum03 Repository last edited on 8 August 2003 at 11:24 am by anemone.cc.gatech.edu
- Eric last edited on 18 June 2003 at 12:17 am by jalisco-lnx.cc.gatech.edu