th1a | replaceafill: For the node sorting, we should probably just take a couple minutes and make a little guessing heuristic to decide which one is most important (the one referred to most overall, say) and then for each unique set of parent nodes say "The most important one and 3 others" and maybe show them all in a tooltip. | 00:42 |
---|---|---|
replaceafill | i think dwelsh will go after the "core" and "additional" parts | 00:44 |
replaceafill | that's the way "cando 2011" sorts them | 00:44 |
th1a | Well, that gets into what we really don't know in the new model. | 00:44 |
replaceafill | right | 00:44 |
th1a | We just should guess based on frequency and sort that way too. | 00:44 |
th1a | He'll never know the difference, it is just a little extra work for us. | 00:45 |
replaceafill | sure | 00:45 |
replaceafill | will you be around the rest of the week? | 00:45 |
replaceafill | i think i'll get to that on friday | 00:45 |
th1a | But you know, computers are good at counting. | 00:45 |
replaceafill | :D | 00:45 |
th1a | I'll be driving home Friday. | 00:45 |
th1a | Not exactly sure when. | 00:46 |
th1a | I'll let you know. | 00:46 |
replaceafill | cool, i'll work on the other5 stories in the meantime :) | 00:46 |
th1a | Also, in the term filter view you could put in parentheses next to the term the number of sections. | 00:46 |
th1a | [ ] Fall 2011 (5 sections) | 00:46 |
replaceafill | ah | 00:46 |
replaceafill | kk, will do | 00:46 |
*** replaceafill has quit IRC | 02:33 | |
*** th1a has quit IRC | 02:51 | |
*** menesis has quit IRC | 04:08 | |
*** th1a has joined #schooltool | 04:20 | |
*** th1a has quit IRC | 05:14 | |
*** th1a has joined #schooltool | 05:14 | |
*** menesis has joined #schooltool | 09:16 | |
*** menesis has quit IRC | 10:37 | |
*** aelkner has joined #schooltool | 14:39 | |
*** aelkner has quit IRC | 14:45 | |
*** aelkner has joined #schooltool | 14:46 | |
*** pgulley has joined #schooltool | 15:45 | |
*** dreich has joined #schooltool | 15:45 | |
*** replaceafill has joined #schooltool | 16:49 | |
pgulley | replaceafill, driech and I just wanted to check up with you | 17:07 |
replaceafill | pgulley, can we talk in 30 mins? i'm getting breakfast | 17:08 |
pgulley | sure, we're here | 17:08 |
replaceafill | kk, bb in 30 | 17:08 |
replaceafill | pgulley, back | 17:25 |
pgulley | perfect. jelkner just mentioned that you had some concerns, we thought it was worth addressing | 17:25 |
replaceafill | well... as i told jelkner, maybe i should just go over the code and change some things i don't like | 17:26 |
replaceafill | i haven't looked closely though | 17:26 |
dreich | you can tell us what you don't like, and we'll try to improve it | 17:26 |
replaceafill | but i would really appreciate if you add tests for the features you're developing | 17:27 |
dreich | yeah, we've definitely gotten way ahead of ourselves | 17:27 |
pgulley | of course, jelkner and matt have beat that one into us, we're planning on feature-freezing after we address things today to get tests up to date | 17:27 |
replaceafill | having a good test coverage would make easy for me or anyone else to get into the code | 17:27 |
replaceafill | and change stuff | 17:27 |
replaceafill | quick question | 17:28 |
replaceafill | why do you need those init2 methods? | 17:28 |
pgulley | images | 17:28 |
replaceafill | is it me, or are they for "postprocessing" the object once it's added? | 17:29 |
pgulley | yes, that's basically it | 17:29 |
pgulley | images need a 'directory path' | 17:29 |
pgulley | so that the browser can access them. that doesn't exist until after they've been added | 17:29 |
replaceafill | right | 17:29 |
replaceafill | i think you could break that logic inside the object's class | 17:30 |
replaceafill | but again, it's easier to do it | 17:30 |
replaceafill | could they at least be renamed from "init2"? | 17:30 |
replaceafill | to something more understandable | 17:30 |
dreich | process_image_url, pgulley? | 17:30 |
pgulley | yes okay. | 17:30 |
replaceafill | since you're probably going to slow down now, with the feature-freeze, you should start working on your own branches | 17:31 |
replaceafill | and do "full commits" with good comments | 17:32 |
replaceafill | when i see "merged" as the commit message... | 17:32 |
replaceafill | you know, it's confusing | 17:32 |
replaceafill | if i want to identify when you did what at what point | 17:32 |
dreich | by "full commit", do you mean a new commit for each new test or feature we add? | 17:33 |
replaceafill | dreich, i mean, a cleaner commit, one that doesn't have "prints" on it | 17:33 |
replaceafill | one that when you see the diff, you don't get any debug noise | 17:33 |
dreich | okay, right | 17:33 |
pgulley | ah yes. because we're juggling code between the two of us it's often hard- we're working on features in parallel. | 17:34 |
replaceafill | right, that's why i said "you're probably going to slow down now" | 17:34 |
replaceafill | but it's possible to go fast on your own branches | 17:34 |
replaceafill | we do it in schooltool | 17:34 |
pgulley | we'll keep the juggling in a separate branch, and only push to the main branch when things are clean, then? | 17:34 |
replaceafill | add pyflakes and pep8 to your dev environments | 17:35 |
replaceafill | you have moved a lot of code | 17:35 |
replaceafill | and there are lots of unnecessary imports in the modules | 17:35 |
replaceafill | get rid of those | 17:35 |
replaceafill | i think pep8check is in the buildout | 17:36 |
replaceafill | yep | 17:36 |
replaceafill | bin/pep8check | 17:36 |
replaceafill | src/pyquiz/schema.py:161:1: E101 indentation contains mixed spaces and tabs | 17:36 |
replaceafill | small things that make going through the code easier | 17:37 |
dreich | :/ wow, that's not good | 17:37 |
replaceafill | i know :/ | 17:37 |
dreich | yeah, thanks for reminding us | 17:37 |
replaceafill | one thing i really don't want is to slow you down | 17:37 |
replaceafill | but as i think he told you, jelkner needs reliability on the new features | 17:37 |
dreich | yeah, jelkner's slowing us down anyway | 17:38 |
dreich | for the best | 17:38 |
replaceafill | so, do you know how to add a test? | 17:38 |
dreich | yes | 17:38 |
dreich | we've done so for subquizzes, but nothing else | 17:38 |
replaceafill | i vote for small focused tests | 17:38 |
replaceafill | many of them | 17:38 |
replaceafill | pyquiz is not huge anyway | 17:39 |
replaceafill | so you can run the tests really quickly | 17:39 |
replaceafill | try to guarantee basic stuff first | 17:39 |
dreich | i was modelling the subquiz test on quiz_management.txt, but yeah, that's a better idea | 17:39 |
replaceafill | dreich, right, existing tests are not a good model probably | 17:39 |
replaceafill | see those huge unorganized narratives at the beginning | 17:40 |
replaceafill | not good | 17:40 |
dreich | ok | 17:40 |
replaceafill | get rid of those remaining "import *" please | 17:40 |
dreich | yessir! | 17:41 |
dreich | what else should we fix? | 17:43 |
*** replaceafill_ has joined #schooltool | 17:43 | |
*** replaceafill_ has joined #schooltool | 17:43 | |
*** replaceafill has quit IRC | 17:43 | |
*** replaceafill_ is now known as replaceafill | 17:44 | |
replaceafill | sorry, got disconnected | 17:44 |
replaceafill | dreich, pgulley could you tell me what new resources does pyquiz have? | 17:44 |
replaceafill | i see a "bucket" now | 17:45 |
pgulley | subquizzes, too | 17:45 |
dreich | yeah, the bucket's a new feature that just started being implemented when we decided to freeze | 17:45 |
dreich | so I'm just cutting off user access to it for now | 17:46 |
replaceafill | what is it for? | 17:46 |
dreich | joe youcha's user stories | 17:46 |
pgulley | sharing questions between users outside of quizzes, basically | 17:46 |
dreich | we'll have 'buckets' of questions, from which random questions can be drawn to create quizzes | 17:46 |
replaceafill | hmm ok | 17:47 |
pgulley | perhaps a better name is in order | 17:47 |
replaceafill | SubQuizQuestion.__init__ | 17:49 |
replaceafill | to me, the title logic should go into the view | 17:49 |
replaceafill | not the resource | 17:49 |
replaceafill | or at least a property on the object | 17:49 |
dreich | I figured it would be good to keep there because it's seen in more than one view | 17:49 |
replaceafill | then use a property | 17:49 |
replaceafill | not the __init__ | 17:50 |
dreich | ok, cool | 17:50 |
replaceafill | what if jelkner comes tomorrow complaining about he wants 30 chars ... | 17:50 |
dreich | ....very good point | 17:51 |
replaceafill | what about .index? | 17:51 |
replaceafill | why is that needed? | 17:51 |
pgulley | another part of the image directory path. that is another thing that can be stream-lined. | 17:51 |
pgulley | we discovered __name__ a bit after we implimented that, basically | 17:52 |
replaceafill | path_form = '/download'? | 17:53 |
pgulley | it is appended to and then stored as the image_url | 17:53 |
replaceafill | is that for getting an url like: | 17:53 |
replaceafill | http://example.com/download/..../.../.../ | 17:53 |
replaceafill | ? | 17:53 |
pgulley | so the final image_url is /download/quiz.id/question.id/choice.id | 17:53 |
pgulley | ye | 17:53 |
pgulley | s | 17:54 |
replaceafill | so, if tomorrow i want to virtualhost several pyquizzes in the same server | 17:54 |
replaceafill | all of them will point to the same path | 17:54 |
replaceafill | or if i want to use http://example.com/randohere/mypyquiz | 17:54 |
replaceafill | the path will still point to /download | 17:55 |
pgulley | no, no. only if they have the same url. it is then appended to the base pyquiz url in the template | 17:55 |
pgulley | with request.application_url | 17:56 |
replaceafill | ah ok | 17:56 |
replaceafill | the path still looks "funny" to me | 17:56 |
replaceafill | like it doesn't belong there | 17:57 |
replaceafill | maybe traversal could be use | 17:57 |
replaceafill | used* | 17:57 |
pgulley | it is a little bit of a clunky solution, yes. | 17:58 |
replaceafill | def duplicate(self, newparent)? | 17:58 |
replaceafill | that needs to be fixed | 17:58 |
replaceafill | i wanted to use .copy for that | 17:58 |
dreich | is used either to duplicate a question within a quiz or to copy it to a new quiz | 17:58 |
dreich | what should I fix about the code? | 17:59 |
replaceafill | dreich, you copy the existing object and attach it to any parent in the caller code | 17:59 |
replaceafill | not send the newparent | 17:59 |
replaceafill | something like: | 17:59 |
replaceafill | ... | 17:59 |
replaceafill | question = existing_question.copy(...) | 17:59 |
replaceafill | newparent[name] = question | 18:00 |
replaceafill | ... | 18:00 |
dreich | but for computing the image url using what's now called init2() | 18:00 |
dreich | the object needs to be added to its parent before init2() can be called | 18:00 |
replaceafill | then you probably need events | 18:00 |
replaceafill | see all your init2() calls in a lot of places | 18:00 |
dreich | events? | 18:01 |
replaceafill | it puts responsability on a lot of callers | 18:01 |
replaceafill | what if i create an object and forget to call "init2" | 18:01 |
replaceafill | that's why i say you may use traversal for that | 18:01 |
replaceafill | traversal is computed on request | 18:02 |
replaceafill | your paths seem fixed | 18:02 |
replaceafill | (at first glance ofc) | 18:02 |
replaceafill | to me "download" should be a container | 18:03 |
replaceafill | or something like that | 18:03 |
replaceafill | not a string we use | 18:03 |
pgulley | I don't think so- download is really just a keyword and the files are stored on the objects | 18:03 |
pgulley | having a separate download container would be an unnecessary duplication. | 18:04 |
replaceafill | why do you need the keyword again? | 18:04 |
pgulley | It should be able to work with traversal how it is | 18:04 |
pgulley | because if we point just to the object path it should be returning the object. | 18:05 |
pgulley | download is caught by the url parser, then all the file serving is handled by one view | 18:05 |
replaceafill | download is a view? | 18:05 |
pgulley | not exactly. but basically. | 18:05 |
pgulley | actually yes, for all intents it is | 18:06 |
dreich | pgulley, you're the image guy, but I can't think of any reason not to make download a view explicitly | 18:06 |
pgulley | I mean there already is | 18:06 |
pgulley | login.download_attachment | 18:06 |
dreich | why not selectionquestion.download? | 18:07 |
replaceafill | oh my... | 18:07 |
replaceafill | blob = context['quizzes'][rec['first']][rec['second']][rec['third']][rec['fourth']].image | 18:08 |
pgulley | yes | 18:08 |
pgulley | sorry about that | 18:08 |
replaceafill | np | 18:08 |
pgulley | it's ugly. | 18:08 |
replaceafill | it's the kind of code *i* write :/ | 18:08 |
replaceafill | that's why i think it could be better :) | 18:08 |
pgulley | dreich, because we don't want a separate download view for every object | 18:09 |
*** carthur has joined #schooltool | 18:09 | |
replaceafill | can you explain downloadAttachment pgulley | 18:09 |
pgulley | yes | 18:09 |
replaceafill | pgulley, you could create one | 18:09 |
replaceafill | do we have a delete view? | 18:09 |
replaceafill | in pyqui | 18:09 |
replaceafill | z | 18:09 |
dreich | (btw, replaceafill, carthur is an intern working with us, we've been teaching him python and pyramid) | 18:10 |
replaceafill | pyquiz.views.login.DeleteView | 18:10 |
replaceafill | dreich, excellent :) | 18:10 |
pgulley | so the url parser gets something in the form of 'download/{first.id}/{second.id}/{third.id}... | 18:10 |
carthur | Hi replaceafill | 18:10 |
replaceafill | hey carthur | 18:10 |
replaceafill | nice to meet you | 18:10 |
carthur | you too | 18:10 |
replaceafill | hope you're enjoying your pyramid learning :) | 18:10 |
replaceafill | these guys are really good, stick to them :D | 18:11 |
replaceafill | pgulley, what if there's a 16th id? | 18:11 |
replaceafill | not possible? ;) | 18:11 |
pgulley | and any url in that form is passed to the download_attachment view. | 18:11 |
pgulley | well actually | 18:11 |
pgulley | I wanted to have a more extensible regular expression that could handle any number of id's | 18:12 |
pgulley | but pyramid didn't like it very much | 18:12 |
pgulley | the plan was to revist it eventually | 18:12 |
replaceafill | pgulley, ok | 18:12 |
replaceafill | add tests for it first | 18:13 |
replaceafill | then you can axe it the way you want | 18:13 |
pgulley | right, tests are the first priority here | 18:13 |
replaceafill | ok, i'll go through the code deeply during the weekend | 18:14 |
replaceafill | two days ago | 18:14 |
replaceafill | i tried to run the app, and got an .index related error in a view | 18:14 |
pgulley | do you remember which view? it may've been a subquiz thing where we hadn't completely merged the features | 18:14 |
replaceafill | pgulley, i was trying to update grades i think | 18:15 |
replaceafill | i dont remember exactly, sorry | 18:15 |
replaceafill | pgulley, dreich use login.txt as a model for your tests | 18:15 |
pgulley | perfect. | 18:15 |
replaceafill | that one could be easily be login1.txt, login2.txt, etc | 18:16 |
dreich | alright | 18:16 |
replaceafill | my point is that each part tries to test a use case of the login view | 18:16 |
dreich | but we shouldn't actually split them to their atoms? | 18:16 |
dreich | only close? | 18:16 |
replaceafill | split them is better imho | 18:17 |
replaceafill | all those browser in login.txt are independent too | 18:17 |
pgulley | so one browser object per test. | 18:18 |
replaceafill | if you think the test data needs to be improved, do it | 18:18 |
dreich | any reason to not split the existing tests, like login.txt, while we're at it? | 18:18 |
replaceafill | dreich, feel free to | 18:18 |
replaceafill | just make sure you don't miss something while splitting | 18:18 |
replaceafill | dreich, also | 18:18 |
replaceafill | there are helpers for those tests | 18:18 |
replaceafill | like addPerson | 18:19 |
dreich | yes, they're awesome | 18:19 |
replaceafill | add as much as you can | 18:19 |
replaceafill | so your test focus on exactly one thing | 18:19 |
replaceafill | instead of going through all the forms to add a couple of questions | 18:19 |
replaceafill | when you want to test is the "duplicate" view | 18:19 |
dreich | ok, avoid redundant tests | 18:20 |
replaceafill | ok, i think that's it from me | 18:20 |
replaceafill | i'll probably have more questions for you next week | 18:20 |
replaceafill | after i understand your new architecture better | 18:20 |
replaceafill | i'll create a branch for my changes and point you to it | 18:21 |
replaceafill | and we can then discuss | 18:21 |
replaceafill | just for the record: i think you're doing a great job | 18:21 |
replaceafill | :) | 18:21 |
dreich | awesome, thanks! | 18:21 |
dreich | and i'm glad you think so, though maybe you won't once you look at the code better :P | 18:22 |
replaceafill | :D | 18:22 |
replaceafill | ah | 18:22 |
replaceafill | last thing | 18:22 |
replaceafill | evolution | 18:22 |
pgulley | ahhh yes | 18:22 |
dreich | yes, we need help with that | 18:22 |
replaceafill | at first, i wanted to have evolution the same way we do in schooltool | 18:23 |
replaceafill | once the server starts, the evolve scripts are run | 18:23 |
replaceafill | and the data evolved | 18:23 |
replaceafill | repoze.evolution can help | 18:23 |
replaceafill | but then i saw the way the karl project handles evolution | 18:23 |
replaceafill | through scripts | 18:23 |
replaceafill | and i liked it | 18:23 |
dreich | this? http://karlproject.org/ | 18:24 |
replaceafill | https://github.com/karlproject | 18:24 |
replaceafill | https://github.com/karlproject/karl/blob/master/karl/scripts/evolve.py | 18:25 |
replaceafill | it's the same logic | 18:25 |
dreich | what's karl written in? | 18:25 |
replaceafill | python :) | 18:25 |
replaceafill | using pyramid :) | 18:25 |
dreich | oh, awesome! | 18:26 |
replaceafill | so, basically, you create an utility for the manager | 18:26 |
dreich | i was worried we were gonna have to translate some zope script or something | 18:26 |
dreich | which is less fun | 18:26 |
replaceafill | which contains the logic for the evolve | 18:26 |
dreich | but that's cool | 18:26 |
replaceafill | you can have as many evolve scripts as you need | 18:26 |
replaceafill | and the evolution manager takes care of annotating the db | 18:27 |
dreich | ok | 18:27 |
replaceafill | http://pypi.python.org/pypi/repoze.evolution/ | 18:28 |
replaceafill | unfortunately it seems like the repoze.org domain is down :( | 18:28 |
replaceafill | but you can install the egg from pypi | 18:28 |
replaceafill | what do you need evolution for? | 18:29 |
dreich | as of now, only for adding a new variable to quizzes | 18:31 |
dreich | "accessible_by" | 18:31 |
pgulley | jeff's deployment is out-of-date | 18:31 |
dreich | which has a perfectly sane default of [created_by] | 18:32 |
replaceafill | make it a class attribute | 18:32 |
replaceafill | and make sure the callers set it | 18:33 |
replaceafill | for instance if you set it in the class as: | 18:33 |
replaceafill | accessible_by = None | 18:33 |
replaceafill | make sure the code that uses it understand None | 18:33 |
replaceafill | in that case even if the existing instance doesnt have the attribute, it will get it from the class | 18:33 |
replaceafill | you use evolution for more complex stuff | 18:34 |
dreich | the problem is that as of now, they don't even have that attribute | 18:34 |
replaceafill | again, use a class attribute | 18:35 |
replaceafill | next time the code looks for: | 18:35 |
replaceafill | existing_old_quiz.accessible_by | 18:35 |
replaceafill | it won't give you an error | 18:35 |
replaceafill | what is accessible_by btw? :) | 18:35 |
dreich | but the first time the view looks for it and doesn't find it, it will give an error, right? | 18:36 |
dreich | (and it's the list of teachers that can view the quiz, either because they created it or because it was shared with them) | 18:36 |
replaceafill | hhmm, to me that should be a different component | 18:37 |
replaceafill | something that handles that | 18:37 |
replaceafill | which references to the quiz | 18:37 |
replaceafill | like [{'quiz': q1, 'teachers': [id1, id2, id3]} | 18:38 |
replaceafill | or something like that | 18:38 |
replaceafill | outside the quiz | 18:38 |
dreich | stored where then? | 18:38 |
replaceafill | some other container | 18:38 |
replaceafill | you could have more logic added to it | 18:39 |
replaceafill | without affecting the quiz resource | 18:39 |
replaceafill | i know it's yagni | 18:39 |
dreich | i feel like just leaving it as an attribute is the simplest and smallest way to do it | 18:40 |
dreich | (the teachers are being stored as usernames, not objects) | 18:40 |
replaceafill | i understand | 18:40 |
replaceafill | i just think it may get difficult to "extract" it | 18:41 |
replaceafill | anyway | 18:41 |
replaceafill | going back to the evolution part | 18:41 |
replaceafill | "but the first time the view looks for it and doesn't find it, it will give an error, right?" | 18:41 |
replaceafill | when the view tries to access the attribute and sees None, the view knows it's an "old" quiz | 18:41 |
replaceafill | and can react | 18:41 |
replaceafill | but if you want to go with the evolve script, that's fine | 18:42 |
replaceafill | i just think it's not necessary | 18:42 |
dreich | ok, cool, that works | 18:42 |
replaceafill | kk | 18:43 |
replaceafill | ok, guys, back to work for me | 18:43 |
dreich | we'll use karl's evolution eventually, but that's later | 18:43 |
replaceafill | +1 | 18:43 |
dreich | alright, we're off to work then! | 18:43 |
*** paulproteus has quit IRC | 19:00 | |
*** paulproteus has joined #schooltool | 19:07 | |
replaceafill | th1a, zyt? | 19:47 |
*** carthur_ has joined #schooltool | 20:41 | |
*** carthur has quit IRC | 20:41 | |
*** pgulley has quit IRC | 20:59 | |
*** dreich has quit IRC | 21:02 | |
*** carthur_ has quit IRC | 21:12 | |
*** dreich has joined #schooltool | 21:35 | |
*** dreich has quit IRC | 22:38 | |
*** replaceafill has quit IRC | 23:07 | |
*** th1a has quit IRC | 23:57 |
Generated by irclog2html.py 2.15.1 by Marius Gedminas - find it at mg.pov.lt!