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

Last change on this file since 13241 was 13176, checked in by Henrik Bettermann, 9 years ago

Include Python test.

  • Property svn:keywords set to Id
File size: 24.3 KB
Line 
1## $Id: tests.py 13176 2015-07-18 05:08:36Z 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        # Reserve beds.
261        self.browser.getControl("Switch reservation", index=0).click()
262        self.assertTrue('No item selected' in self.browser.contents)
263        ctrl = self.browser.getControl(name='val_id')
264        ctrl.getControl(value='hall-1_A_101_A').selected = True
265        ctrl.getControl(value='hall-1_A_101_B').selected = True
266        ctrl.getControl(value='hall-1_A_101_C').selected = True
267        ctrl.getControl(value='hall-1_A_101_D').selected = True
268        self.browser.getControl("Switch reservation", index=0).click()
269        self.assertTrue('Successfully switched beds: hall-1_A_101_A (reserved)'
270            in self.browser.contents)
271        self.assertEqual(self.app['hostels']['hall-1'][
272            'hall-1_A_101_D'].bed_type, 'regular_female_reserved')
273        self.assertTrue('A_101_A&nbsp;&nbsp;' in self.browser.contents)
274        # The catalog has been updated.
275        results = cat.searchResults(
276            bed_type=('regular_female_all', 'regular_female_all'))
277        results = [(x.bed_id, x.bed_type) for x in results]
278        self.assertEqual(results,
279            [(u'hall-1_A_101_E', u'regular_female_all'),
280             (u'hall-1_B_101_D', u'regular_female_all'),
281             (u'hall-1_B_101_E', u'regular_female_all')])
282        results = cat.searchResults(
283            bed_type=('regular_female_reserved', 'regular_female_reserved'))
284        results = [(x.bed_id, x.bed_type) for x in results]
285        self.assertEqual(results,
286            [(u'hall-1_A_101_A', u'regular_female_reserved'),
287             (u'hall-1_A_101_B', u'regular_female_reserved'),
288             (u'hall-1_A_101_C', u'regular_female_reserved'),
289             (u'hall-1_A_101_D', u'regular_female_reserved')])
290        # Change hostel configuration with one bed booked.
291        hall['hall-1_A_101_E'].owner = u'anyid'
292        notify(grok.ObjectModifiedEvent(hall['hall-1_A_101_E']))
293        hall.beds_for_fresh = ['A', 'E']
294        hall.beds_for_all = ['D']
295        self.browser.getControl("Update all beds").click()
296        expected = '...9 empty beds removed, 9 beds added, 1 occupied beds modified...'
297        self.assertMatches(expected,self.browser.contents)
298        # Updating beds (including booked beds!) does update catalog.
299        results = cat.searchResults(
300            bed_type=('regular_female_all', 'regular_female_all'))
301        results = [(x.bed_id, x.bed_type) for x in results]
302        self.assertEqual(results,
303            [(u'hall-1_B_101_D', u'regular_female_all'),])
304        # Unreserve beds.
305        ctrl = self.browser.getControl(name='val_id')
306        ctrl.getControl(value='hall-1_A_101_A').selected = True
307        ctrl.getControl(value='hall-1_A_101_B').selected = True
308        ctrl.getControl(value='hall-1_A_101_C').selected = True
309        ctrl.getControl(value='hall-1_A_101_D').selected = True
310        self.browser.getControl("Switch reservation", index=0).click()
311        assert self.app['hostels']['hall-1'][
312            'hall-1_A_101_D'].bed_type == 'regular_female_all'
313        self.assertFalse(expected in self.browser.contents)
314        # Release bed which has previously been booked.
315        bedticket = BedTicket()
316        bedticket.booking_session = 2004
317        bedticket.bed_coordinates = u'anything'
318        self.student['accommodation'].addBedTicket(bedticket)
319        self.app['hostels']['hall-1']['hall-1_A_101_D'].owner = self.student_id
320        self.browser.open(self.container_path + '/hall-1/manage')
321        ctrl = self.browser.getControl(name='val_id')
322        self.browser.getControl("Release selected beds", index=0).click()
323        self.assertMatches("...No item selected...", self.browser.contents)
324        ctrl = self.browser.getControl(name='val_id')
325        ctrl.getControl(value='hall-1_A_101_D').selected = True
326        self.browser.getControl("Release selected beds", index=0).click()
327        self.assertMatches(
328          '...Successfully released beds: hall-1_A_101_D (%s)...' % self.student_id,
329          self.browser.contents)
330        self.assertMatches(bedticket.bed_coordinates,
331          u' -- booking cancelled on <YYYY-MM-DD hh:mm:ss> UTC --')
332        # If we release a free be, nothing will happen.
333        ctrl = self.browser.getControl(name='val_id')
334        ctrl.getControl(value='hall-1_A_101_D').selected = True
335        self.browser.getControl("Release selected beds", index=0).click()
336        self.assertMatches(
337          '...No allocated bed selected...', self.browser.contents)
338        # Managers can manually allocate eligible students after cancellation.
339        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
340        # 'not occupied' is not accepted.
341        self.browser.getControl("Save").click()
342        self.assertMatches(
343            "...No valid student id...",
344            self.browser.contents)
345        # Invalid student ids are not accepted.
346        self.browser.getControl(name="form.owner").value = 'nonsense'
347        self.browser.getControl("Save").click()
348        self.assertMatches(
349            "...Either student does not exist or student "
350            "is not in accommodation session...",
351            self.browser.contents)
352        self.browser.getControl(name="form.owner").value = self.student_id
353        self.browser.getControl("Save").click()
354        self.assertMatches("...Form has been saved...", self.browser.contents)
355        # Students can only be allocated once.
356        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_B')
357        self.browser.getControl(name="form.owner").value = self.student_id
358        self.browser.getControl("Save").click()
359        self.assertMatches(
360            "...This student resides in bed hall-1_A_101_A...",
361            self.browser.contents)
362        # If we open the same form again, we will be redirected to hostel
363        # manage page. Beds must be released first before they can be
364        # allocated to other students.
365        self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A')
366        self.assertEqual(self.browser.url,
367            self.container_path + '/hall-1/@@manage#tab2')
368        # Updating the beds again will not affect the allocation and also
369        # the bed numbering remains the same.
370        old_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
371        old_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
372        self.browser.getControl("Update all beds").click()
373        # 8 beds have been removed and re-added, 2 beds remains untouched
374        # because they are occupied.
375        expected = '...8 empty beds removed, 8 beds added, 0 occupied beds modified...'
376        self.assertMatches(expected,self.browser.contents)
377        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
378        new_owner = self.app['hostels']['hall-1']['hall-1_A_101_A'].owner
379        self.assertEqual(new_number, old_number)
380        self.assertEqual(new_owner, old_owner)
381        # If we change the bed type of an allocated bed, the modification will
382        # be indicated.
383        hall.blocks_for_female = ['B']
384        hall.blocks_for_male = ['A']
385        self.browser.getControl("Update all beds").click()
386        expected = '...8 empty beds removed, 8 beds added, ' + \
387            '2 occupied beds modified (hall-1_A_101_A, hall-1_A_101_E, )...'
388        self.assertMatches(expected,self.browser.contents)
389        new_number = self.app['hostels']['hall-1']['hall-1_A_101_A'].bed_number
390        # Also the number of the bed has changed.
391        self.assertFalse(new_number == old_number)
392        # The number of occupied beds are displayed on container page.
393        self.browser.open(self.container_path)
394        self.assertTrue('2 of 10' in self.browser.contents)
395        # Remove entire hostel.
396        self.browser.open(self.manage_container_path)
397        ctrl = self.browser.getControl(name='val_id')
398        value = ctrl.options[0]
399        ctrl.getControl(value=value).selected = True
400        self.browser.getControl("Remove selected", index=0).click()
401        self.assertTrue('Successfully removed' in self.browser.contents)
402        # Catalog is empty.
403        results = cat.searchResults(
404            bed_type=('regular_female_all', 'regular_female_all'))
405        results = [x for x in results]
406        assert len(results) == 0
407        # Actions are logged.
408        logcontent = open(self.logfile).read()
409        self.assertTrue(
410            'hall-1 - 9 empty beds removed, 9 beds added, 1 occupied '
411            'beds modified (hall-1_A_101_E, )'
412            in logcontent)
413
414    def test_clear_hostels(self):
415        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
416        self.browser.open(self.container_path)
417        self.browser.getLink("Manage accommodation").click()
418        self.browser.getControl("Add hostel").click()
419        self.browser.getControl("Create hostel").click()
420        hall = self.app['hostels']['hall-1']
421        hall.blocks_for_female = ['A','B']
422        hall.rooms_per_floor = 1
423        hall.beds_for_fresh = ['A']
424        hall.beds_for_returning = ['B']
425        hall.beds_for_final = ['C']
426        hall.beds_for_all = ['D','E']
427        self.browser.open(self.container_path + '/hall-1/manage')
428        self.browser.getControl("Update all beds").click()
429        cat = queryUtility(ICatalog, name='beds_catalog')
430        results = cat.searchResults(bed_type=(None, None))
431        self.assertEqual(len(results), 11)
432        self.browser.getControl("Clear hostel").click()
433        self.assertEqual(len(self.app['hostels']['hall-1']), 0)
434        # Only the bed in hall-x remains in the catalog.
435        results = cat.searchResults(bed_type=(None, None))
436        self.assertEqual(len(results), 1)
437        # We can clear all hostels at the same time.
438        self.browser.open(self.manage_container_path)
439        self.browser.getControl("Clear all hostels").click()
440        results = cat.searchResults(bed_type=(None, None))
441        self.assertEqual(len(results), 0)
442        # Both actions have been logged.
443        logcontent = open(self.logfile).read()
444        self.assertTrue('INFO - zope.mgr - hostels.browser.HostelManageFormPage'
445                        ' - hall-1 - cleared' in logcontent)
446        self.assertTrue('zope.mgr - hostels.browser.HostelsContainerManagePage'
447                        ' - hostels - all hostels cleared' in logcontent)
448
449class ExportTests(HostelsFullSetup):
450
451    layer = FunctionalLayer
452
453    def setUp(self):
454        super(ExportTests, self).setUp()
455        self.workdir = tempfile.mkdtemp()
456        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
457        return
458
459    def test_export_hostels(self):
460        exporter = HostelExporter()
461        exporter.export_all(self.app, self.outfile)
462        result = open(self.outfile, 'rb').read()
463        self.assertEqual(
464            result,
465            'beds_for_all,beds_for_final,beds_for_fresh,beds_for_pre,'
466            'beds_for_returning,beds_reserved,blocks_for_female,'
467            'blocks_for_male,floors_per_block,hostel_id,hostel_name,maint_fee,'
468            'rooms_per_floor,sort_id,special_handling\r\n,,,,,[],,,1,'
469            'hall-x,Hall 1,0.0,2,10,regular\r\n'
470            )
471        return
472
473    def test_export_beds(self):
474        exporter = BedExporter()
475        exporter.export_all(self.app, self.outfile)
476        result = open(self.outfile, 'rb').read()
477        self.assertEqual(
478            result,
479            'bed_id,bed_number,bed_type,owner,hall,block,room,bed,'
480            'special_handling,sex,bt\r\nhall_block_room_bed,1,a_b_c,,'
481            'hall,block,room,bed,a,b,c\r\n'
482            )
483        return
484
485    def tearDown(self):
486        super(ExportTests, self).tearDown()
487        clearSite()
488        shutil.rmtree(os.path.dirname(self.outfile))
489
490class HostelProcessorTest(HostelsFullSetup):
491
492    layer = FunctionalLayer
493
494    def test_import(self):
495        self.processor = HostelProcessor()
496        self.workdir = tempfile.mkdtemp()
497        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
498        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
499        num, num_warns, fin_file, fail_file = self.processor.doImport(
500            self.csv_file, HOSTEL_HEADER_FIELDS)
501        self.assertEqual(num_warns,0)
502        self.assertEqual(len(self.app['hostels'].keys()), 11) # including hall-x
503        self.assertEqual(self.app['hostels'][
504            'block-a-upper-hostel'].hostel_id,'block-a-upper-hostel')
505        self.assertEqual(self.app['hostels'][
506            'block-a-upper-hostel'].beds_for_final, ['A', 'B'])
507        logcontent = open(self.logfile).read()
508        self.assertTrue(
509            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
510            "updated: "
511            "beds_for_pre=['G'], floors_per_block=1, "
512            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
513            "hostel_id=block-a-upper-hostel, "
514            "sort_id=20, beds_for_returning=['C', 'D'], "
515            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
516            "blocks_for_female=['A']"
517            in logcontent)
518        shutil.rmtree(os.path.dirname(fin_file))
519        shutil.rmtree(self.workdir)
520        return
521
522    def test_import_update(self):
523        self.processor = HostelProcessor()
524        self.workdir = tempfile.mkdtemp()
525        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
526        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
527        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
528        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
529        num, num_warns, fin_file, fail_file = self.processor.doImport(
530            self.csv_file, HOSTEL_HEADER_FIELDS)
531        # We import the same file in update mode
532        num, num_warns, fin_file, fail_file = self.processor.doImport(
533            self.csv_file, HOSTEL_HEADER_FIELDS, 'update')
534        self.assertEqual(num_warns,0)
535        logcontent = open(self.logfile).read()
536        self.assertTrue(
537            "Hostel Processor - sample_hostel_data - block-a-upper-hostel - "
538            "updated: "
539            "beds_for_pre=['G'], floors_per_block=1, "
540            "beds_for_final=['A', 'B'], rooms_per_floor=32, "
541            "hostel_id=block-a-upper-hostel, "
542            "sort_id=20, beds_for_returning=['C', 'D'], "
543            "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], "
544            "blocks_for_female=['A']"
545            in logcontent)
546        shutil.rmtree(os.path.dirname(fin_file))
547        shutil.rmtree(self.workdir)
548        return
Note: See TracBrowser for help on using the repository browser.