/usr/lib/python2.7/dist-packages/schooltool/intervention/README.txt is in python-schooltool.intervention 2.7.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | =====================
Student Interventions
=====================
This package supplies the school with a number of objects for tracking
interventions with students who are having either academic or behavioral
problems. Objects include messages passed between concerned faculty members
and goals that are established for the student.
Let's import some zope stuff before we use it.
>>> from zope.component import (provideHandler, provideUtility,
... getMultiAdapter)
>>> from zope.lifecycleevent.interfaces import (IObjectAddedEvent,
... IObjectRemovedEvent)
>>> from zope.interface.verify import verifyObject
We'll set up the app object, a schoolyear and a current term.
>>> from schooltool.testing import setup as stsetup
>>> from datetime import date
>>> from schooltool.schoolyear.interfaces import ISchoolYearContainer
>>> from schooltool.schoolyear.schoolyear import SchoolYear
>>> schoolyear = SchoolYear("Sample", date(2004, 9, 1), date(2005, 12, 20))
>>> ISchoolYearContainer(app)['2004-2005'] = schoolyear
>>> from schooltool.term.interfaces import ITermContainer
>>> from schooltool.term.term import Term
>>> term = Term('Sample', date(2004, 9, 1), date(2004, 12, 20))
>>> terms = ITermContainer(app)
>>> terms['2004-fall'] = term
>>> from schooltool.term.tests import setUpDateManagerStub
>>> setUpDateManagerStub(date(2004, 9, 1), term)
Interventions
-------------
The intervention objects make up a hierarchy starting at the intervention root
which hangs off of the application root. It has one InterventionSchoolYear
object per school year each containing whatever InterventionStudent objects
were created for the given year. The InterventionStudent objects have two
containers under them for messages and goals.
The first adapter we have is to get the intervention root.
>>> from schooltool.intervention import intervention, interfaces
>>> interventionRoot = interfaces.IInterventionRoot(app)
>>> verifyObject(interfaces.IInterventionRoot, interventionRoot)
True
It will have no InterventionSchoolYear objects in it yet because they are not
created until needed. They are auto-vivified when the adapter that seeks
them is called.
>>> [key for key in interventionRoot]
[]
We have an adapter that adapts a SchoolYear to an InterventionSchoolYear.
It will create the missing InterventionSchoolYear and return it to us.
>>> interventionSchoolYear = interfaces.IInterventionSchoolYear(schoolyear)
>>> verifyObject(interfaces.IInterventionSchoolYear, interventionSchoolYear)
True
>>> [key for key in interventionRoot]
[u'2004-2005']
If we adapt the app to IInterventionSchoolYear it will return the one for the
current school year which is the same year.
>>> interventionSchoolYear is interfaces.IInterventionSchoolYear(app)
True
Let's create a student and a contact for the parent and set both emails.
>>> from schooltool.contact.interfaces import IContact, IContactable
>>> from schooltool.contact.contact import Contact
>>> def addEmail(person):
... IContact(person).email = '%s@example.com' % person.__name__
>>> from schooltool.basicperson.person import BasicPerson
>>> jdoe = BasicPerson('jdoe', 'John', 'Doe')
>>> app['persons']['jdoe'] = jdoe
>>> addEmail(jdoe)
>>> parent1 = app['persons']['parent1'] = Contact()
>>> parent1.email = 'parent1@provider.com'
>>> IContactable(jdoe).contacts.add(parent1)
We can adapt from a student, schoolyear pair to an InterventionStudent.
Since this is the first time, it will be created automatically.
>>> [key for key in interventionSchoolYear]
[]
>>> jdoeIntervention = getMultiAdapter((jdoe, schoolyear),
... interfaces.IInterventionStudent)
>>> [key for key in interventionSchoolYear]
[u'jdoe']
>>> verifyObject(interfaces.IInterventionStudent, jdoeIntervention)
True
We can also adapt directly from the student, in which case the current school
year will be assumed. Since that year is the same, we will get the same
InterventionStudent back.
>>> jdoeIntervention is interfaces.IInterventionStudent(jdoe)
True
We also have adapter from any intervention object, InterventionStudent and
below, to the student object itself.
>>> from schooltool.person.interfaces import IPerson
>>> IPerson(jdoeIntervention) is jdoe
True
The new InterventionStudent will have messages and goals containers in it.
>>> [key for key in jdoeIntervention]
[u'goals', u'messages']
>>> jdoeMessages = jdoeIntervention['messages']
>>> verifyObject(interfaces.IInterventionMessages, jdoeMessages)
True
>>> len(jdoeMessages)
0
>>> jdoeGoals = jdoeIntervention['goals']
>>> verifyObject(interfaces.IInterventionGoals, jdoeGoals)
True
>>> len(jdoeGoals)
0
We'll note that the student adapter returns the correct student for both
containers.
>>> IPerson(jdoeMessages) is jdoe
True
>>> IPerson(jdoeGoals) is jdoe
True
Intervention Messagess
----------------------
Now we will create some InterventionMessage objects for the student and put
them in the student's InterventionMessages container.
First, we'll need to register the dummy mail sender for testing.
>>> from schooltool.email.interfaces import IEmailUtility
>>> from schooltool.intervention import sendmail
>>> provideUtility(sendmail.TestMailDelivery(), provides=IEmailUtility)
>>> manager_user = BasicPerson('manager', 'SchoolTool', 'Manager')
>>> app['persons']['manager'] = manager_user
>>> addEmail(manager_user)
We will create person objects for some teachers and advisors.
>>> teacher1 = BasicPerson('teacher1', '1', 'Teacher')
>>> app['persons']['teacher1'] = teacher1
>>> addEmail(teacher1)
>>> teacher2 = BasicPerson('teacher2', '2', 'Teacher')
>>> app['persons']['teacher2'] = teacher2
>>> addEmail(teacher2)
>>> advisor1 = BasicPerson('advisor1', '1', 'Advisor')
>>> app['persons']['advisor1'] = advisor1
>>> addEmail(advisor1)
>>> advisor2 = BasicPerson('advisor2', '2', 'Advisor')
>>> app['persons']['advisor2'] = advisor2
>>> addEmail(advisor2)
Now we'll create a message and add it to the container.
>>> body = "John has been a bad student."
>>> message1 = app['messages']['message1'] = intervention.InterventionMessage(body)
>>> message1.sender.add(IContact(teacher1))
>>> message1.recipients.add(IContact(teacher2))
>>> message1.recipients.add(IContact(advisor1))
>>> verifyObject(interfaces.IInterventionMessage, message1)
True
>>> jdoeMessages['1'] = message1
We'll call the method in sendmail for emailing the message which causes the
dummy mail sender to print out the email that would otherwise be sent to
a real SMTP server.
>>> email = sendmail.sendInterventionMessageEmail(message1)
From: teacher1@example.com
To: advisor1@example.com, teacher2@example.com
Subject: INTERVENTION MESSAGE: John Doe
1 Teacher writes:
<BLANKLINE>
John has been a bad student.
We'll note that the student adapter returns the correct student.
>>> IPerson(message1) is jdoe
True
We'll create another message with different sender and recipients and add it
to the container. The difference will be reflected in the email message.
>>> body = "John still needs to learn to behave."
>>> message2 = app['messages']['message2'] = intervention.InterventionMessage(body)
>>> message2.sender.add(IContact(teacher2))
>>> message2.recipients.add(IContact(advisor1))
>>> message2.recipients.add(IContact(advisor2))
>>> jdoeMessages['2'] = message2
>>> email = sendmail.sendInterventionMessageEmail(message2)
From: teacher2@example.com
To: advisor1@example.com, advisor2@example.com
Subject: INTERVENTION MESSAGE: John Doe
2 Teacher writes:
<BLANKLINE>
John still needs to learn to behave.
Intervention Goals
------------------
Let's create some InterventionGoal objects for the student and put them in
the student's InterventionGoals container.
>>> from datetime import date
>>> goal1 = app['goals']['goal1'] = intervention.InterventionGoal('be nicer', date(2004, 9, 1),
... 'bad behaviour', 'smart',
... 'nicer to clasmates', 'teach manners')
>>> goal1.creator.add(IContact(teacher1))
>>> goal1.persons_responsible = [advisor1, advisor2]
>>> verifyObject(interfaces.IInterventionGoal, goal1)
True
>>> jdoeGoals['1'] = goal1
We'll call the method in sendmail for emailing the goal which causes the
dummy mail sender to print out the email that would otherwise be sent to
a real SMTP server.
>>> emails = sendmail.sendInterventionGoalAddEmail(goal1)
From: teacher1@example.com
To: advisor1@example.com, advisor2@example.com
Subject: INTERVENTION GOAL ADDED: John Doe
The following goal was added for John Doe:
<BLANKLINE>
Presenting concerns
-------------------
<BLANKLINE>
bad behaviour
<BLANKLINE>
Goal
----
<BLANKLINE>
be nicer
<BLANKLINE>
Strengths
---------
<BLANKLINE>
smart
<BLANKLINE>
Indicators
----------
<BLANKLINE>
nicer to clasmates
<BLANKLINE>
Intervention
------------
<BLANKLINE>
teach manners
<BLANKLINE>
Timeline
--------
<BLANKLINE>
...
<BLANKLINE>
Persons responsible
-------------------
<BLANKLINE>
1 Advisor
2 Advisor
<BLANKLINE>
Intervention Center
-------------------
<BLANKLINE>
http://127.0.0.1/schooltool.interventions/2004-2005/jdoe
<BLANKLINE>
We'll note that the student adapter returns the correct student.
>>> IPerson(goal1) is jdoe
True
As it turns out, goals have an at_one_time_responsible attribute that basically
is a union of every different value persons_responsible has had for the life
of the goal object. Presently it's the same as persons_responsible.
>>> sorted([IPerson(contact).username for contact in goal1.at_one_time_responsible])
['advisor1', 'advisor2']
If we change the persons_responsible to have a new user, we'll see that the
at_one_time_responsible attribute will have a record of all the historical
values.
>>> goal1.persons_responsible = [teacher1]
>>> sorted([IPerson(contact).username for contact in goal1.at_one_time_responsible])
['advisor1', 'advisor2', 'teacher1']
We'll restore persons_responsible for later tests.
>>> goal1.persons_responsible = [advisor1, advisor2]
Note that at_one_time_responsible was not effected.
>>> sorted([IPerson(contact).username for contact in goal1.at_one_time_responsible])
['advisor1', 'advisor2', 'teacher1']
Let's add a second one.
>>> goal2 = app['goals']['goal2'] = intervention.InterventionGoal('passing grades', date.today(),
... 'bad grades', 'friendly',
... 'grades are passing', 'tutor student')
>>> goal2.creator.add(IContact(teacher1))
>>> goal2.persons_responsible = [teacher1, advisor2]
>>> jdoeGoals['2'] = goal2
Send the goal email.
>>> emails = sendmail.sendInterventionGoalAddEmail(goal2)
From: teacher1@example.com
To: advisor2@example.com, teacher1@example.com
Subject: INTERVENTION GOAL ADDED: John Doe
The following goal was added for John Doe:
<BLANKLINE>
Presenting concerns
-------------------
<BLANKLINE>
bad grades
<BLANKLINE>
Goal
----
<BLANKLINE>
passing grades
<BLANKLINE>
Strengths
---------
<BLANKLINE>
friendly
<BLANKLINE>
Indicators
----------
<BLANKLINE>
grades are passing
<BLANKLINE>
Intervention
------------
<BLANKLINE>
tutor student
<BLANKLINE>
Timeline
--------
<BLANKLINE>
...
<BLANKLINE>
Persons responsible
-------------------
<BLANKLINE>
1 Teacher
2 Advisor
<BLANKLINE>
Intervention Center
-------------------
<BLANKLINE>
http://127.0.0.1/schooltool.interventions/2004-2005/jdoe
<BLANKLINE>
We chose date.today() as the timeline for our goals because we wanted to test
right away the method in our sendmail module that notifies the persons
responsible via email when the timeline has been reached for a goal. We'll
call this method and see the email messages that get generated. Also, we'll
need to add the schooltool manager user that's expected by the routine to be
present.
>>> from schooltool.intervention import sendmail
>>> notified = sendmail.sendInterventionGoalNotifyEmails()
From: teacher1@example.com
To: advisor1@example.com, advisor2@example.com
Subject: INTERVENTION GOAL DUE: John Doe
Please follow the link below to update the follow up notes and, if
appropriate, the goal met status of the intervention goal for John Doe.
<BLANKLINE>
http://127.0.0.1/schooltool.interventions/.../jdoe/goals/1/@@editGoal.html
<BLANKLINE>
From: teacher1@example.com
To: advisor2@example.com, teacher1@example.com
Subject: INTERVENTION GOAL DUE: John Doe
Please follow the link below to update the follow up notes and, if
appropriate, the goal met status of the intervention goal for John Doe.
<BLANKLINE>
http://127.0.0.1/schooltool.interventions/.../jdoe/goals/2/@@editGoal.html
<BLANKLINE>
>>> len(notified)
2
If we call the same routine again, we will get nothing because the notified
flags have been set on the goals.
>>> notified = sendmail.sendInterventionGoalNotifyEmails()
>>> len(notified)
0
Convenience functions
---------------------
We have a couple of convenience functions for converting contacts to sorted
lists of names (by last name) or email.
>>> from schooltool.contact.interfaces import IContact
>>> intervention.contactName(IContact(teacher1))
'1 Teacher'
>>> intervention.contactsName([IContact(teacher1), IContact(advisor1)])
['1 Advisor', '1 Teacher']
>>> intervention.contactsEmail([IContact(teacher1), IContact(advisor1)])
[u'advisor1@example.com', u'teacher1@example.com']
|