source: main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py @ 13174

Last change on this file since 13174 was 13170, checked in by Henrik Bettermann, 10 years ago

More docs.

  • Property svn:keywords set to Id
File size: 24.2 KB
Line 
1## $Id: tests.py 13170 2015-07-15 11:26:22Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""
19Tests for hostels and their UI components.
20"""
21import os
22import shutil
23import tempfile
24import grok
25import pytz
26from datetime import datetime, timedelta
27from zope.event import notify
28from zope.interface.verify import verifyClass, verifyObject
29from zope.component.hooks import setSite, clearSite
30from zope.testbrowser.testing import Browser
31from zope.security.interfaces import Unauthorized
32from zope.catalog.interfaces import ICatalog
33from zope.component import queryUtility
34from waeup.kofa.app import University
35from waeup.kofa.hostels.interfaces import (
36    IHostelsContainer, IHostel, IBed)
37from waeup.kofa.hostels.container import HostelsContainer
38from waeup.kofa.hostels.hostel import Hostel, Bed
39from waeup.kofa.hostels.batching import HostelProcessor
40from waeup.kofa.hostels.export import BedExporter, HostelExporter
41from waeup.kofa.testing import (FunctionalLayer, FunctionalTestCase)
42from waeup.kofa.students.student import Student
43from waeup.kofa.students.accommodation import BedTicket
44from waeup.kofa.university.department import Department
45
46HOSTEL_SAMPLE_DATA = open(
47    os.path.join(os.path.dirname(__file__), 'sample_hostel_data.csv'),
48    'rb').read()
49
50HOSTEL_HEADER_FIELDS = HOSTEL_SAMPLE_DATA.split(
51    '\n')[0].split(',')
52
53class HostelsContainerTestCase(FunctionalTestCase):
54
55    layer = FunctionalLayer
56
57    def test_interfaces(self):
58        # Make sure the correct interfaces are implemented.
59        self.assertTrue(
60            verifyClass(
61                IHostelsContainer, HostelsContainer)
62            )
63        self.assertTrue(
64            verifyObject(
65                IHostelsContainer, HostelsContainer())
66            )
67        self.assertTrue(
68            verifyClass(
69                IHostel, Hostel)
70            )
71        self.assertTrue(
72            verifyObject(
73                IHostel, Hostel())
74            )
75        self.assertTrue(
76            verifyClass(
77                IBed, Bed)
78            )
79        bed = Bed()
80        bed.bed_id = u'a_b_c_d'
81        bed.bed_type = u'a_b_c'
82        self.assertTrue(
83            verifyObject(
84                IBed, bed)
85            )
86        return
87
88    def test_base(self):
89        # We cannot call the fundamental methods of a base in that case
90        container = HostelsContainer()
91        hostel = Hostel()
92        # We cannot add arbitrary objects
93        department = Department()
94        self.assertRaises(
95            TypeError, container.addHostel, department)
96        self.assertRaises(
97            TypeError, hostel.addBed, department)
98        # Application is expired if startdate or enddate are not set
99        # or current datetime is outside application period.
100        self.assertTrue(container.expired)
101        delta = timedelta(days=10)
102        container.startdate = datetime.now(pytz.utc) - delta
103        self.assertTrue(container.expired)
104        container.enddate = datetime.now(pytz.utc) + delta
105        self.assertFalse(container.expired)
106
107class HostelsFullSetup(FunctionalTestCase):
108
109    def setUp(self):
110        super(HostelsFullSetup, self).setUp()
111
112        # Setup a sample site for each test
113        app = University()
114        self.dc_root = tempfile.mkdtemp()
115        app['datacenter'].setStoragePath(self.dc_root)
116
117        # Prepopulate the ZODB...
118        self.getRootFolder()['app'] = app
119        # we add the site immediately after creation to the
120        # ZODB. Catalogs and other local utilities are not setup
121        # before that step.
122        self.app = self.getRootFolder()['app']
123        # Set site here. Some of the following setup code might need
124        # to access grok.getSite() and should get our new app then
125        setSite(app)
126
127        # Add student with subobjects
128        student = Student()
129        student.firstname = u'Anna'
130        student.lastname = u'Tester'
131        student.reg_number = u'123'
132        student.matric_number = u'234'
133        student.sex = u'f'
134        self.app['students'].addStudent(student)
135        self.student_id = student.student_id
136        self.student = self.app['students'][self.student_id]
137        self.student['studycourse'].current_session = 2004
138        self.student['studycourse'].entry_session = 2004
139        # The students_catalog must be informed that the
140        # session attribute has changed
141        notify(grok.ObjectModifiedEvent(self.student))
142
143        # Set accommodation_session
144        self.app['hostels'].accommodation_session = 2004
145
146        # Create a hostel
147        hostel = Hostel()
148        hostel.hostel_id = u'hall-x'
149        self.app['hostels'][hostel.hostel_id] = hostel
150
151        # Create a bed
152        bed = Bed()
153        bed.bed_id = u'hall_block_room_bed'
154        bed.bed_number = 1
155        bed.bed_type = u'a_b_c'
156        self.app['hostels'][hostel.hostel_id][bed.bed_id] = bed
157
158        self.container_path = 'http://localhost/app/hostels'
159        self.student_path = 'http://localhost/app/students/%s' % self.student_id
160        self.manage_container_path = self.container_path + '/@@manage'
161        self.add_hostel_path = self.container_path + '/addhostel'
162
163        # Put the prepopulated site into test ZODB and prepare test
164        # browser
165        self.browser = Browser()
166        self.browser.handleErrors = False
167
168        self.logfile = os.path.join(
169            self.app['datacenter'].storage, 'logs', 'hostels.log')
170
171    def tearDown(self):
172        super(HostelsFullSetup, self).tearDown()
173        clearSite()
174        shutil.rmtree(self.dc_root)
175
176class BedCatalogTests(HostelsFullSetup):
177
178    layer = FunctionalLayer
179
180    def test_get_catalog(self):
181        # We can get a beds catalog if we wish
182        cat = queryUtility(ICatalog, name='beds_catalog')
183        assert cat is not None
184
185    def test_search_by_type(self):
186        # We can find a certain bed
187        cat = queryUtility(ICatalog, name='beds_catalog')
188        results = cat.searchResults(bed_type=(u'a_b_c', u'a_b_c'))
189        results = [x for x in results] # Turn results generator into list
190        assert len(results) == 1
191        assert results[0] is self.app['hostels']['hall-x']['hall_block_room_bed']
192
193    def test_search_by_owner(self):
194        # We can find a certain bed
195        myobj = self.app['hostels']['hall-x']['hall_block_room_bed']
196        myobj.owner = u'abc'
197        notify(grok.ObjectModifiedEvent(myobj))
198        cat = queryUtility(ICatalog, name='beds_catalog')
199        results = cat.searchResults(owner=(u'abc', u'abc'))
200        results = [x for x in results] # Turn results generator into list
201        assert len(results) == 1
202        assert results[0] is self.app['hostels']['hall-x']['hall_block_room_bed']
203
204class HostelsUITests(HostelsFullSetup):
205
206    layer = FunctionalLayer
207
208    def test_anonymous_access(self):
209        # Anonymous users can't access hostels containers
210        self.assertRaises(
211            Unauthorized, self.browser.open, self.manage_container_path)
212        return
213
214    def test_add_search_edit_delete_manage_hostels(self):
215        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
216        self.browser.open(self.container_path)
217        self.browser.getLink("Manage accommodation").click()
218        self.assertEqual(self.browser.headers['Status'], '200 Ok')
219        self.assertEqual(self.browser.url, self.manage_container_path)
220        self.browser.getControl("Add hostel").click()
221        self.assertEqual(self.browser.headers['Status'], '200 Ok')
222        self.assertEqual(self.browser.url, self.add_hostel_path)
223        self.browser.getControl("Create hostel").click()
224        self.assertEqual(self.browser.headers['Status'], '200 Ok')
225        self.assertTrue('Hostel created' in self.browser.contents)
226        self.browser.open(self.container_path + '/addhostel')
227        self.browser.getControl("Create hostel").click()
228        self.assertTrue('The hostel already exists' in self.browser.contents)
229        hall = self.app['hostels']['hall-1']
230        hall.blocks_for_female = ['A','B']
231        self.browser.open(self.container_path + '/hall-1')
232        expected = '''...<ul id="form.blocks_for_female" ><li>Block A</li>
233<li>Block B</li></ul>...'''
234        self.assertMatches(expected,self.browser.contents)
235        self.browser.open(self.container_path + '/hall-1/manage')
236        self.browser.getControl(name="form.rooms_per_floor").value = '1'
237        self.browser.getControl("Save").click()
238        self.assertTrue('Form has been saved' in self.browser.contents)
239        # Since the testbrowser does not support Javascrip the
240        # save action cleared the settings above and we have to set them
241        # again
242        self.assertTrue(len(hall.blocks_for_female) == 0)
243        hall.blocks_for_female = ['A','B']
244        hall.beds_for_fresh = ['A']
245        hall.beds_for_returning = ['B']
246        hall.beds_for_final = ['C']
247        hall.beds_for_all = ['D','E']
248        self.browser.getControl("Update all beds").click()
249        expected = '...0 empty beds removed, 10 beds added, 0 occupied beds modified ()...'
250        self.assertMatches(expected,self.browser.contents)
251        cat = queryUtility(ICatalog, name='beds_catalog')
252        results = cat.searchResults(
253            bed_type=('regular_female_all', 'regular_female_all'))
254        results = [(x.bed_id, x.bed_type) for x in results]
255        self.assertEqual(results,
256            [(u'hall-1_A_101_D', u'regular_female_all'),
257             (u'hall-1_A_101_E', u'regular_female_all'),
258             (u'hall-1_B_101_D', u'regular_female_all'),
259             (u'hall-1_B_101_E', u'regular_female_all')])
260
261        # Reserve bed
262        self.browser.getControl("Switch reservation", index=0).click()
263        self.assertTrue('No item selected' in self.browser.contents)
264        ctrl = self.browser.getControl(name='val_id')
265        ctrl.getControl(value='hall-1_A_101_A').selected = True
266        ctrl.getControl(value='hall-1_A_101_B').selected = True
267        ctrl.getControl(value='hall-1_A_101_C').selected = True
268        ctrl.getControl(value='hall-1_A_101_D').selected = True
269        self.browser.getControl("Switch reservation", index=0).click()
270        self.assertTrue('Successfully switched beds: hall-1_A_101_A (reserved)'
271            in self.browser.contents)
272        self.assertEqual(self.app['hostels']['hall-1'][
273            'hall-1_A_101_D'].bed_type, 'regular_female_reserved')
274        self.assertTrue('A_101_A&nbsp;&nbsp;' in self.browser.contents)
275        # The catalog has been updated
276        results = cat.searchResults(
277            bed_type=('regular_female_all', 'regular_female_all'))
278        results = [(x.bed_id, x.bed_type) for x in results]
279        self.assertEqual(results,
280            [(u'hall-1_A_101_E', u'regular_female_all'),
281             (u'hall-1_B_101_D', u'regular_female_all'),
282             (u'hall-1_B_101_E', u'regular_female_all')])
283        results = cat.searchResults(
284            bed_type=('regular_female_reserved', 'regular_female_reserved'))
285        results = [(x.bed_id, x.bed_type) for x in results]
286        self.assertEqual(results,
287            [(u'hall-1_A_101_A', u'regular_female_reserved'),
288             (u'hall-1_A_101_B', u'regular_female_reserved'),
289             (u'hall-1_A_101_C', u'regular_female_reserved'),
290             (u'hall-1_A_101_D', u'regular_female_reserved')])
291
292        # Change hostel configuration with one bed booked
293        hall['hall-1_A_101_E'].owner = u'anyid'
294        notify(grok.ObjectModifiedEvent(hall['hall-1_A_101_E']))
295        hall.beds_for_fresh = ['A', 'E']
296        hall.beds_for_all = ['D']
297        self.browser.getControl("Update all beds").click()
298        expected = '...9 empty beds removed, 9 beds added, 1 occupied beds modified...'
299        self.assertMatches(expected,self.browser.contents)
300        # Updating beds (including booked beds!) does update catalog
301        results = cat.searchResults(
302            bed_type=('regular_female_all', 'regular_female_all'))
303        results = [(x.bed_id, x.bed_type) for x in results]
304        self.assertEqual(results,
305            [(u'hall-1_B_101_D', u'regular_female_all'),])
306        # Unreserve bed
307        ctrl = self.browser.getControl(name='val_id')
308        ctrl.getControl(value='hall-1_A_101_A').selected = True
309        ctrl.getControl(value='hall-1_A_101_B').selected = True
310        ctrl.getControl(value='hall-1_A_101_C').selected = True
311        ctrl.getControl(value='hall-1_A_101_D').selected = True
312        self.browser.getControl("Switch reservation", index=0).click()
313        assert self.app['hostels']['hall-1'][
314            'hall-1_A_101_D'].bed_type == 'regular_female_all'
315        self.assertFalse(expected in self.browser.contents)
316        # Release bed which has previously been booked
317        bedticket = BedTicket()
318        bedticket.booking_session = 2004
319        bedticket.bed_coordinates = u'anything'
320        self.student['accommodation'].addBedTicket(bedticket)
321        self.app['hostels']['hall-1']['hall-1_A_101_D'].owner = self.student_id
322        self.browser.open(self.container_path + '/hall-1/manage')
323        ctrl = self.browser.getControl(name='val_id')
324        self.browser.getControl("Release selected beds", index=0).click()
325        self.assertMatches("...No item selected...", self.browser.contents)
326        ctrl = self.browser.getControl(name='val_id')
327        ctrl.getControl(value='hall-1_A_101_D').selected = True
328        self.browser.getControl("Release selected beds", index=0).click()
329        self.assertMatches(
330          '...Successfully released beds: hall-1_A_101_D (%s)...' % self.student_id,
331          self.browser.contents)
332        self.assertMatches(bedticket.bed_coordinates,
333          u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> UTC --')
334        # If we release a free be, nothing will happen
335        ctrl = self.browser.getControl(name='val_id')
336        ctrl.getControl(value='hall-1_A_101_D').selected = True
337        self.browser.getControl("Release selected beds", index=0).click()
338        self.assertMatches(
339          '...No allocated bed selected...', self.browser.contents)
340        # Managers can manually allocate eligible students after cancellation
341        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
342        # 'not occupied' is not accepted
343        self.browser.getControl("Save").click()
344        self.assertMatches(
345            "...No valid student id...",
346            self.browser.contents)
347        # Invalid student ids are not accepted
348        self.browser.getControl(name="form.owner").value = 'nonsense'
349        self.browser.getControl("Save").click()
350        self.assertMatches(
351            "...Either student does not exist or student "
352            "is not in accommodation session...",
353            self.browser.contents)
354        self.browser.getControl(name="form.owner").value = self.student_id
355        self.browser.getControl("Save").click()
356        self.assertMatches("...Form has been saved...", self.browser.contents)
357        # Students can only be allocated once
358        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_B')
359        self.browser.getControl(name="form.owner").value = self.student_id
360        self.browser.getControl("Save").click()
361        self.assertMatches(
362            "...This student resides in bed hall-1_A_101_A...",
363            self.browser.contents)
364        # If we open the same form again, we will be redirected to hostel
365        # manage page. Beds must be released first before they can be
366        # allocated to other students.
367        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
368        self.assertEqual(self.browser.url,
369            self.container_path + '/hall-1/@@manage#tab2')
370        # Updating the beds again will not affect the allocation and also
371        # the bed numbering remains the same
372        old_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
373        old_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
374        self.browser.getControl("Update all beds").click()
375        # 8 beds have been removed and re-added, 2 beds remains untouched
376        # because they are occupied
377        expected = '...8 empty beds removed, 8 beds added, 0 occupied beds modified...'
378        self.assertMatches(expected,self.browser.contents)
379        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
380        new_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
381        self.assertEqual(new_number, old_number)
382        self.assertEqual(new_owner, old_owner)
383        # If we change the bed type of an allocated bed, the modification will
384        # be indicated
385        hall.blocks_for_female = ['B']
386        hall.blocks_for_male = ['A']
387        self.browser.getControl("Update all beds").click()
388        expected = '...8 empty beds removed, 8 beds added, ' + \
389            '2 occupied beds modified (hall-1_A_101_A, hall-1_A_101_E, )...'
390        self.assertMatches(expected,self.browser.contents)
391        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
392        # Also the number of the bed has changed.
393        self.assertFalse(new_number == old_number)
394        # The number of occupied beds are displayed on container page.
395        self.browser.open(self.container_path)
396        self.assertTrue('2 of 10' in self.browser.contents)
397        # Remove entire hostel
398        self.browser.open(self.manage_container_path)
399        ctrl = self.browser.getControl(name='val_id')
400        value = ctrl.options[0]
401        ctrl.getControl(value=value).selected = True
402        self.browser.getControl("Remove selected", index=0).click()
403        self.assertTrue('Successfully removed' in self.browser.contents)
404        # Catalog is empty
405        results = cat.searchResults(
406            bed_type=('regular_female_all', 'regular_female_all'))
407        results = [x for x in results]
408        assert len(results) == 0
409        # Actions are logged.
410        logcontent = open(self.logfile).read()
411        self.assertTrue(
412            'hall-1 - 9 empty beds removed, 9 beds added, 1 occupied '
413            'beds modified (hall-1_A_101_E, )'
414            in logcontent)
415
416    def test_clear_hostels(self):
417        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
418        self.browser.open(self.container_path)
419        self.browser.getLink("Manage accommodation").click()
420        self.browser.getControl("Add hostel").click()
421        self.browser.getControl("Create hostel").click()
422        hall = self.app['hostels']['hall-1']
423        hall.blocks_for_female = ['A','B']
424        hall.rooms_per_floor = 1
425        hall.beds_for_fresh = ['A']
426        hall.beds_for_returning = ['B']
427        hall.beds_for_final = ['C']
428        hall.beds_for_all = ['D','E']
429        self.browser.open(self.container_path + '/hall-1/manage')
430        self.browser.getControl("Update all beds").click()
431        cat = queryUtility(ICatalog, name='beds_catalog')
432        results = cat.searchResults(bed_type=(None, None))
433        self.assertEqual(len(results), 11)
434        self.browser.getControl("Clear hostel").click()
435        self.assertEqual(len(self.app['hostels']['hall-1']), 0)
436        # Only the bed in hall-x remains in the catalog.
437        results = cat.searchResults(bed_type=(None, None))
438        self.assertEqual(len(results), 1)
439        # We can clear all hostels at the same time.
440        self.browser.open(self.manage_container_path)
441        self.browser.getControl("Clear all hostels").click()
442        results = cat.searchResults(bed_type=(None, None))
443        self.assertEqual(len(results), 0)
444        # Both actions have been logged.
445        logcontent = open(self.logfile).read()
446        self.assertTrue('INFO - zope.mgr - hostels.browser.HostelManageFormPage'
447                        ' - hall-1 - cleared' in logcontent)
448        self.assertTrue('zope.mgr - hostels.browser.HostelsContainerManagePage'
449                        ' - hostels - all hostels cleared' in logcontent)
450
451class ExportTests(HostelsFullSetup):
452
453    layer = FunctionalLayer
454
455    def setUp(self):
456        super(ExportTests, self).setUp()
457        self.workdir = tempfile.mkdtemp()
458        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
459        return
460
461    def test_export_hostels(self):
462        exporter = HostelExporter()
463        exporter.export_all(self.app, self.outfile)
464        result = open(self.outfile, 'rb').read()
465        self.assertEqual(
466            result,
467            'beds_for_all,beds_for_final,beds_for_fresh,beds_for_pre,'
468            'beds_for_returning,beds_reserved,blocks_for_female,'
469            'blocks_for_male,floors_per_block,hostel_id,hostel_name,maint_fee,'
470            'rooms_per_floor,sort_id,special_handling\r\n,,,,,[],,,1,'
471            'hall-x,Hall 1,0.0,2,10,regular\r\n'
472            )
473        return
474
475    def test_export_beds(self):
476        exporter = BedExporter()
477        exporter.export_all(self.app, self.outfile)
478        result = open(self.outfile, 'rb').read()
479        self.assertEqual(
480            result,
481            'bed_id,bed_number,bed_type,owner,hall,block,room,bed,'
482            'special_handling,sex,bt\r\nhall_block_room_bed,1,a_b_c,,'
483            'hall,block,room,bed,a,b,c\r\n'
484            )
485        return
486
487    def tearDown(self):
488        super(ExportTests, self).tearDown()
489        clearSite()
490        shutil.rmtree(os.path.dirname(self.outfile))
491
492class HostelProcessorTest(HostelsFullSetup):
493
494    layer = FunctionalLayer
495
496    def test_import(self):
497        self.processor = HostelProcessor()
498        self.workdir = tempfile.mkdtemp()
499        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
500        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
501        num, num_warns, fin_file, fail_file = self.processor.doImport(
502            self.csv_file, HOSTEL_HEADER_FIELDS)
503        self.assertEqual(num_warns,0)
504        self.assertEqual(len(self.app['hostels'].keys()), 11) # including hall-x
505        self.assertEqual(self.app['hostels'][
506            'block-a-upper-hostel'].hostel_id,'block-a-upper-hostel')
507        self.assertEqual(self.app['hostels'][
508            'block-a-upper-hostel'].beds_for_final, ['A', 'B'])
509        logcontent = open(self.logfile).read()
510        self.assertTrue(
511            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
512            "updated: "
513            "beds_for_pre=['G'], floors_per_block=1, "
514            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
515            "hostel_id=block-a-upper-hostel, "
516            "sort_id=20, beds_for_returning=['C', 'D'], "
517            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
518            "blocks_for_female=['A']"
519            in logcontent)
520        shutil.rmtree(os.path.dirname(fin_file))
521        shutil.rmtree(self.workdir)
522        return
523
524    def test_import_update(self):
525        self.processor = HostelProcessor()
526        self.workdir = tempfile.mkdtemp()
527        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
528        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
529        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
530        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
531        num, num_warns, fin_file, fail_file = self.processor.doImport(
532            self.csv_file, HOSTEL_HEADER_FIELDS)
533        # We import the same file in update mode
534        num, num_warns, fin_file, fail_file = self.processor.doImport(
535            self.csv_file, HOSTEL_HEADER_FIELDS, 'update')
536        self.assertEqual(num_warns,0)
537        logcontent = open(self.logfile).read()
538        self.assertTrue(
539            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
540            "updated: "
541            "beds_for_pre=['G'], floors_per_block=1, "
542            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
543            "hostel_id=block-a-upper-hostel, "
544            "sort_id=20, beds_for_returning=['C', 'D'], "
545            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
546            "blocks_for_female=['A']"
547            in logcontent)
548        shutil.rmtree(os.path.dirname(fin_file))
549        shutil.rmtree(self.workdir)
550        return
Note: See TracBrowser for help on using the repository browser.