source: main/waeup.kofa/trunk/src/waeup/kofa/university/tests/test_export.py @ 16231

Last change on this file since 16231 was 15496, checked in by Henrik Bettermann, 5 years ago

Export course_category.

  • Property svn:keywords set to Id
File size: 23.1 KB
Line 
1## $Id: test_export.py 15496 2019-07-11 19:38:20Z henrik $
2##
3## Copyright (C) 2012 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##
18import os
19import shutil
20import tempfile
21import unittest
22from zope.component import queryUtility
23from zope.interface.verify import verifyObject, verifyClass
24from zope.securitypolicy.interfaces import IPrincipalRoleManager
25from waeup.kofa.interfaces import ICSVExporter
26from waeup.kofa.testing import KofaUnitTestLayer, FunctionalLayer
27from waeup.kofa.university import (
28    FacultiesContainer, Faculty, Department, Course, Certificate,
29    )
30from waeup.kofa.university.export import (
31    FacultyExporter, DepartmentExporter, CourseExporter,
32    CertificateExporter, CertificateCourseExporter,
33    )
34
35class FacultyExporterTest(unittest.TestCase):
36
37    layer = FunctionalLayer
38
39    def setUp(self):
40        self.workdir = tempfile.mkdtemp()
41        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
42        return
43
44    def tearDown(self):
45        shutil.rmtree(self.workdir)
46        return
47
48    def test_ifaces(self):
49        # make sure we fullfill interface contracts
50        obj = FacultyExporter()
51        verifyObject(ICSVExporter, obj)
52        verifyClass(ICSVExporter, FacultyExporter)
53        return
54
55    def test_get_as_utility(self):
56        # we can get a faculty exporter as utility
57        result = queryUtility(ICSVExporter, name="faculties")
58        self.assertTrue(result is not None)
59        return
60
61    def test_export(self):
62        # we can export a set of faculties
63        fac = Faculty('Faculty of Cheese', 'faculty', 'F1')
64        exporter = FacultyExporter()
65        exporter.export([fac], self.outfile)
66        result = open(self.outfile, 'rb').read()
67        self.assertEqual(
68            result,
69            'code,title,title_prefix,users_with_local_roles,'
70            'officer_1,officer_2\r\n'
71            'F1,Faculty of Cheese,faculty,[],,\r\n'
72            )
73        return
74
75    def test_export_to_string(self):
76        # we can export a set of faculties to a string.
77        fac = Faculty('Faculty of Cheese', 'faculty', 'F1')
78        exporter = FacultyExporter()
79        result = exporter.export([fac], filepath=None)
80        self.assertEqual(
81            result,
82            'code,title,title_prefix,users_with_local_roles,'
83            'officer_1,officer_2\r\n'
84            'F1,Faculty of Cheese,faculty,[],,\r\n'
85            )
86        return
87
88    def test_export_all(self):
89        # we can export all faculties in a site
90        container = FacultiesContainer()
91        site = {'faculties':container}
92        fac1 = Faculty('Faculty of Cheese', 'faculty', 'F1')
93        fac2 = Faculty('Centre of Onion', 'centre', 'F2')
94        container.addFaculty(fac1)
95        container.addFaculty(fac2)
96        exporter = FacultyExporter()
97        exporter.export_all(site, self.outfile)
98        result = open(self.outfile, 'rb').read()
99        self.assertEqual(
100            result,
101            'code,title,title_prefix,users_with_local_roles,'
102            'officer_1,officer_2\r\n'
103            'F1,Faculty of Cheese,faculty,[],,\r\n'
104            'F2,Centre of Onion,centre,[],,\r\n'
105            )
106        return
107
108    def test_export_all_to_string(self):
109        # we can export all faculties in a site to a string
110        container = FacultiesContainer()
111        site = {'faculties':container}
112        fac1 = Faculty('Faculty of Cheese', 'faculty', 'F1')
113        fac2 = Faculty('Centre of Onion', 'centre', 'F2')
114        container.addFaculty(fac1)
115        container.addFaculty(fac2)
116        exporter = FacultyExporter()
117        result = exporter.export_all(site, filepath=None)
118        self.assertEqual(
119            result,
120            'code,title,title_prefix,users_with_local_roles,'
121            'officer_1,officer_2\r\n'
122            'F1,Faculty of Cheese,faculty,[],,\r\n'
123            'F2,Centre of Onion,centre,[],,\r\n'
124            )
125        return
126
127class DepartmentExporterTest(unittest.TestCase):
128    # Tests for DepartmentExporter
129
130    layer = FunctionalLayer
131
132    def setUp(self):
133        self.workdir = tempfile.mkdtemp()
134        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
135        # create some departments in a fake site
136        container = FacultiesContainer()
137        self.site = {'faculties':container}
138        self.fac1 = Faculty('Faculty of Cheese', 'faculty', 'F1')
139        self.fac2 = Faculty('Centre of Onion', 'centre', 'F2')
140        container.addFaculty(self.fac1)
141        container.addFaculty(self.fac2)
142        self.dept1 = Department(
143            'Department of Cheddar', 'department', 'D1', 'HoCheese')
144        self.dept2 = Department('Institue of Gouda', 'institute', 'D2')
145        self.dept3 = Department('Department of Rings', 'department', 'D3')
146        self.fac1.addDepartment(self.dept1)
147        self.fac1.addDepartment(self.dept2)
148        self.fac2.addDepartment(self.dept3)
149        role_manager = IPrincipalRoleManager(self.dept1)
150        role_manager.assignRoleToPrincipal(u'bobsrole', u'bob')
151        return
152
153    def tearDown(self):
154        shutil.rmtree(self.workdir)
155        return
156
157    def test_ifaces(self):
158        # make sure we fullfill interface contracts
159        obj = DepartmentExporter()
160        verifyObject(ICSVExporter, obj)
161        verifyClass(ICSVExporter, DepartmentExporter)
162        return
163
164    def test_get_as_utility(self):
165        # we can get a department exporter as utility
166        result = queryUtility(ICSVExporter, name="departments")
167        self.assertTrue(result is not None)
168        return
169
170    def test_export(self):
171        # we can export an iterable of departments
172        exporter = DepartmentExporter()
173        exporter.export([self.dept1], self.outfile)
174        result = open(self.outfile, 'rb').read()
175        self.assertEqual(
176            result,
177            'code,faculty_code,title,title_prefix,users_with_local_roles,'
178            'officer_1,officer_2,officer_3,officer_4\r\n'
179            'D1,F1,Department of Cheddar,department,'
180            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]",'
181            'HoCheese,,,\r\n'
182            )
183        return
184
185    def test_export_to_string(self):
186        # we can export an iterable of departments to a string.
187        exporter = DepartmentExporter()
188        result = exporter.export([self.dept1, self.dept2], filepath=None)
189        self.assertEqual(
190            result,
191            'code,faculty_code,title,title_prefix,users_with_local_roles,'
192            'officer_1,officer_2,officer_3,officer_4\r\n'
193            'D1,F1,Department of Cheddar,department,'
194            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]",'
195            'HoCheese,,,\r\n'
196            'D2,F1,Institue of Gouda,institute,[],,,,\r\n'
197            )
198        return
199
200    def test_export_all(self):
201        # we can export all depts in a site
202        exporter = DepartmentExporter()
203        exporter.export_all(self.site, self.outfile)
204        result = open(self.outfile, 'rb').read()
205        self.assertEqual(
206            result,
207            'code,faculty_code,title,title_prefix,users_with_local_roles,'
208            'officer_1,officer_2,officer_3,officer_4\r\n'
209            'D1,F1,Department of Cheddar,department,'
210            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]",'
211            'HoCheese,,,\r\n'
212            'D2,F1,Institue of Gouda,institute,[],,,,\r\n'
213            'D3,F2,Department of Rings,department,[],,,,\r\n'
214            )
215        return
216
217    def test_export_all_to_string(self):
218        # we can export all depts in a site to a string
219        exporter = DepartmentExporter()
220        result = exporter.export_all(self.site, filepath=None)
221        self.assertEqual(
222            result,
223            'code,faculty_code,title,title_prefix,users_with_local_roles,'
224            'officer_1,officer_2,officer_3,officer_4\r\n'
225            'D1,F1,Department of Cheddar,department,'
226            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]",'
227            'HoCheese,,,\r\n'
228            'D2,F1,Institue of Gouda,institute,[],,,,\r\n'
229            'D3,F2,Department of Rings,department,[],,,,\r\n'
230            )
231        return
232
233class CourseExporterTest(unittest.TestCase):
234    # Tests for CourseExporter
235
236    layer = FunctionalLayer
237
238    def setUp(self):
239        self.workdir = tempfile.mkdtemp()
240        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
241        # create some departments and courses in a fake site
242        container = FacultiesContainer()
243        self.site = {'faculties':container}
244        self.fac = Faculty('Faculty of Cheese', 'faculty', 'F1')
245        container.addFaculty(self.fac)
246        self.dept1 = Department('Department of Cheddar', 'department', 'D1')
247        self.dept2 = Department('Institue of Gouda', 'institute', 'D2')
248        self.fac.addDepartment(self.dept1)
249        self.fac.addDepartment(self.dept2)
250        self.course1 = Course('Cheese Basics', 'C1')
251        self.course2 = Course('Advanced Cheese Making', 'C2')
252        self.course3 = Course('Selling Cheese', 'C3')
253        self.dept1.courses.addCourse(self.course1)
254        self.dept1.courses.addCourse(self.course2)
255        self.dept2.courses.addCourse(self.course3)
256        return
257
258    def tearDown(self):
259        shutil.rmtree(self.workdir)
260        return
261
262    def test_ifaces(self):
263        # make sure we fullfill interface contracts
264        obj = CourseExporter()
265        verifyObject(ICSVExporter, obj)
266        verifyClass(ICSVExporter, CourseExporter)
267        return
268
269    def test_get_as_utility(self):
270        # we can get a course exporter as utility
271        result = queryUtility(ICSVExporter, name="courses")
272        self.assertTrue(result is not None)
273        return
274
275    def test_export(self):
276        # we can export an iterable of courses
277        exporter = CourseExporter()
278        exporter.export([self.course1], self.outfile)
279        result = open(self.outfile, 'rb').read()
280        self.assertEqual(
281            result,
282            'code,faculty_code,department_code,title,credits,'
283            'passmark,semester,users_with_local_roles,former_course,'
284            'results_validated_by,results_validation_date,'
285            'results_validation_session\r\n'
286            'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n'
287            )
288        return
289
290    def test_export_to_string(self):
291        # we can export an iterable of courses to a string.
292        exporter = CourseExporter()
293        result = exporter.export([self.course1, self.course2], filepath=None)
294        self.assertEqual(
295            result,
296            'code,faculty_code,department_code,title,credits,passmark,'
297            'semester,users_with_local_roles,former_course,'
298            'results_validated_by,results_validation_date,'
299            'results_validation_session\r\n'
300            'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n'
301            'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0,,,\r\n'
302            )
303        return
304
305    def test_export_all(self):
306        # we can export all courses in a site
307        exporter = CourseExporter()
308        exporter.export_all(self.site, self.outfile)
309        result = open(self.outfile, 'rb').read()
310        self.assertEqual(
311            result,
312            'code,faculty_code,department_code,title,credits,passmark,'
313            'semester,users_with_local_roles,former_course,'
314            'results_validated_by,results_validation_date,'
315            'results_validation_session\r\n'
316            'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n'
317            'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0,,,\r\n'
318            'C3,F1,D2,Selling Cheese,0,40,1,[],0,,,\r\n'
319            )
320        return
321
322    def test_export_all_to_string(self):
323        # we can export all courses in a site to a string
324        exporter = CourseExporter()
325        result = exporter.export_all(self.site, filepath=None)
326        self.assertEqual(
327            result,
328            'code,faculty_code,department_code,title,credits,passmark,'
329            'semester,users_with_local_roles,former_course,'
330            'results_validated_by,results_validation_date,'
331            'results_validation_session\r\n'
332            'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n'
333            'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0,,,\r\n'
334            'C3,F1,D2,Selling Cheese,0,40,1,[],0,,,\r\n'
335            )
336        return
337
338class CertificateExporterTest(unittest.TestCase):
339    # Tests for CertificateExporter
340
341    layer = FunctionalLayer
342
343    def setUp(self):
344        self.workdir = tempfile.mkdtemp()
345        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
346        # create some departments and courses in a fake site
347        container = FacultiesContainer()
348        self.site = {'faculties':container}
349        self.fac = Faculty('Faculty of Cheese', 'faculty', 'F1')
350        container.addFaculty(self.fac)
351        self.dept1 = Department('Department of Cheddar', 'department', 'D1')
352        self.dept2 = Department('Institue of Gouda', 'institute', 'D2')
353        self.fac.addDepartment(self.dept1)
354        self.fac.addDepartment(self.dept2)
355        self.course1 = Course('Cheese Basics', 'C1')
356        self.course2 = Course('Advanced Cheese Making', 'C2')
357        self.course3 = Course('Selling Cheese', 'C3')
358        self.dept1.courses.addCourse(self.course1)
359        self.dept1.courses.addCourse(self.course2)
360        self.dept2.courses.addCourse(self.course3)
361        self.cert1 = Certificate(
362            'CERT1', 'Master of Cheese', study_mode=u'ct_ft', start_level=100,
363            end_level=300, application_category='basic')
364        self.cert2 = Certificate(
365            'CERT2', 'Master of Cheddar', study_mode='ct_ft', start_level=400,
366            end_level=700, application_category='cest')
367        self.cert3 = Certificate(
368            'CERT3', 'Cert. of Rubbish', study_mode='dp_pt', start_level=100,
369            end_level=200, application_category='no')
370        self.dept1.certificates.addCertificate(self.cert1)
371        self.dept1.certificates.addCertificate(self.cert2)
372        self.dept2.certificates.addCertificate(self.cert3)
373        role_manager = IPrincipalRoleManager(self.cert1)
374        role_manager.assignRoleToPrincipal(u'bobsrole', u'bob')
375        return
376
377    def tearDown(self):
378        shutil.rmtree(self.workdir)
379        return
380
381    def test_ifaces(self):
382        # make sure we fullfill interface contracts
383        obj = CertificateExporter()
384        verifyObject(ICSVExporter, obj)
385        verifyClass(ICSVExporter, CertificateExporter)
386        return
387
388    def test_get_as_utility(self):
389        # we can get a certificate exporter as utility
390        result = queryUtility(ICSVExporter, name="certificates")
391        self.assertTrue(result is not None)
392        return
393
394    def test_export(self):
395        # we can export an iterable of certificates
396        exporter = CertificateExporter()
397        exporter.export([self.cert1], self.outfile)
398        result = open(self.outfile, 'rb').read()
399        self.assertEqual(
400            result,
401            'code,faculty_code,department_code,title,study_mode,'
402            'degree,start_level,'
403            'end_level,application_category,ratio,school_fee_1,'
404            'school_fee_2,school_fee_3,school_fee_4,'
405            'custom_textline_1,custom_textline_2,'
406            'custom_float_1,custom_float_2,'
407            'users_with_local_roles\r\n'
408            'CERT1,F1,D1,Master of Cheese,ct_ft,,100,300,basic,,,,,,,,,,'
409            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]"\r\n'
410            )
411        return
412
413    def test_export_to_string(self):
414        # we can export an iterable of certificates to a string.
415        exporter = CertificateExporter()
416        result = exporter.export([self.cert1, self.cert2], filepath=None)
417        self.assertEqual(
418            result,
419            'code,faculty_code,department_code,title,study_mode,'
420            'degree,start_level,'
421            'end_level,application_category,ratio,school_fee_1,'
422            'school_fee_2,school_fee_3,school_fee_4,'
423            'custom_textline_1,custom_textline_2,'
424            'custom_float_1,custom_float_2,'
425            'users_with_local_roles\r\n'
426            'CERT1,F1,D1,Master of Cheese,ct_ft,,100,300,basic,,,,,,,,,,'
427            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]"\r\n'
428            'CERT2,F1,D1,Master of Cheddar,ct_ft,,400,700,cest,,,,,,,,,,[]\r\n'
429            )
430        return
431
432    def test_export_all(self):
433        # we can export all certificates in a site
434        exporter = CertificateExporter()
435        exporter.export_all(self.site, self.outfile)
436        result = open(self.outfile, 'rb').read()
437        self.assertEqual(
438            result,
439            'code,faculty_code,department_code,title,study_mode,'
440            'degree,start_level,'
441            'end_level,application_category,ratio,'
442            'school_fee_1,school_fee_2,school_fee_3,school_fee_4,'
443            'custom_textline_1,custom_textline_2,'
444            'custom_float_1,custom_float_2,'
445            'users_with_local_roles\r\n'
446            'CERT1,F1,D1,Master of Cheese,ct_ft,,100,300,basic,,,,,,,,,,'
447            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]"\r\n'
448            'CERT2,F1,D1,Master of Cheddar,ct_ft,,400,700,cest,,,,,,,,,,[]\r\n'
449            'CERT3,F1,D2,Cert. of Rubbish,dp_pt,,100,200,no,,,,,,,,,,[]\r\n'
450            )
451        return
452
453    def test_export_all_to_string(self):
454        # we can export all certificates in a site to a string
455        exporter = CertificateExporter()
456        result = exporter.export_all(self.site, filepath=None)
457        self.assertEqual(
458            result,
459            'code,faculty_code,department_code,title,study_mode,'
460            'degree,start_level,'
461            'end_level,application_category,ratio,'
462            'school_fee_1,school_fee_2,school_fee_3,school_fee_4,'
463            'custom_textline_1,custom_textline_2,'
464            'custom_float_1,custom_float_2,'
465            'users_with_local_roles\r\n'
466            'CERT1,F1,D1,Master of Cheese,ct_ft,,100,300,basic,,,,,,,,,,'
467            '"[{\'user_name\': u\'bob\', \'local_role\': u\'bobsrole\'}]"\r\n'
468            'CERT2,F1,D1,Master of Cheddar,ct_ft,,400,700,cest,,,,,,,,,,[]\r\n'
469            'CERT3,F1,D2,Cert. of Rubbish,dp_pt,,100,200,no,,,,,,,,,,[]\r\n'
470            )
471        return
472
473class CertificateCourseExporterTest(unittest.TestCase):
474    # Tests for CertificateCourseExporter
475
476    layer = KofaUnitTestLayer
477
478    def setUp(self):
479        self.workdir = tempfile.mkdtemp()
480        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
481        # create some departments and courses in a fake site
482        container = FacultiesContainer()
483        self.site = {'faculties':container}
484        self.fac = Faculty('Faculty of Cheese', 'faculty', 'F1')
485        container.addFaculty(self.fac)
486        self.dept1 = Department('Department of Cheddar', 'department', 'D1')
487        self.dept2 = Department('Institue of Gouda', 'institute', 'D2')
488        self.fac.addDepartment(self.dept1)
489        self.fac.addDepartment(self.dept2)
490        self.course1 = Course('Cheese Basics', 'C1')
491        self.course2 = Course('Advanced Cheese Making', 'C2')
492        self.course3 = Course('Selling Cheese', 'C3')
493        self.dept1.courses.addCourse(self.course1)
494        self.dept1.courses.addCourse(self.course2)
495        self.dept2.courses.addCourse(self.course3)
496        self.cert1 = Certificate(
497            'CERT1', 'Master of Cheese', study_mode=u'ct_ft', start_level=100,
498            end_level=300, application_category='basic')
499        self.cert2 = Certificate(
500            'CERT2', 'Master of Cheddar', study_mode='ct_ft', start_level=400,
501            end_level=700, application_category='cest')
502        self.cert3 = Certificate(
503            'CERT3', 'Cert. of Rubbish', study_mode='dp_pt', start_level=100,
504            end_level=200, application_category='no')
505        self.dept1.certificates.addCertificate(self.cert1)
506        self.dept1.certificates.addCertificate(self.cert2)
507        self.dept2.certificates.addCertificate(self.cert3)
508        self.cert1.addCertCourse(self.course1, 100, True)
509        self.cert1.addCertCourse(self.course2, 400, False)
510        self.cert3.addCertCourse(self.course3, 100, False)
511        self.certcourse1 = self.cert1['C1_100']
512        self.certcourse2 = self.cert1['C2_400']
513        self.certcourse3 = self.cert3['C3_100']
514        return
515
516    def tearDown(self):
517        shutil.rmtree(self.workdir)
518        return
519
520    def test_ifaces(self):
521        # make sure we fullfill interface contracts
522        obj = CertificateCourseExporter()
523        verifyObject(ICSVExporter, obj)
524        verifyClass(ICSVExporter, CertificateCourseExporter)
525        return
526
527    def test_get_as_utility(self):
528        # we can get a certificate exporter as utility
529        result = queryUtility(ICSVExporter, name="certificate_courses")
530        self.assertTrue(result is not None)
531        return
532
533    def test_export(self):
534        # we can export an iterable of certificates
535        exporter = CertificateCourseExporter()
536        exporter.export([self.certcourse1], self.outfile)
537        result = open(self.outfile, 'rb').read()
538        self.assertEqual(
539            result,
540            'course,faculty_code,department_code,certificate_code,'
541            'level,mandatory,course_category\r\n'
542            'C1,F1,D1,CERT1,100,1,\r\n'
543            )
544        return
545
546    def test_export_to_string(self):
547        # we can export an iterable of certificates to a string.
548        exporter = CertificateCourseExporter()
549        result = exporter.export(
550            [self.certcourse1, self.certcourse2], filepath=None)
551        self.assertEqual(
552            result,
553            'course,faculty_code,department_code,certificate_code,'
554            'level,mandatory,course_category\r\n'
555            'C1,F1,D1,CERT1,100,1,\r\n'
556            'C2,F1,D1,CERT1,400,0,\r\n'
557            )
558        return
559
560    def test_export_all(self):
561        # we can export all certificates in a site
562        exporter = CertificateCourseExporter()
563        exporter.export_all(self.site, self.outfile)
564        result = open(self.outfile, 'rb').read()
565        self.assertEqual(
566            result,
567            'course,faculty_code,department_code,certificate_code,'
568            'level,mandatory,course_category\r\n'
569            'C1,F1,D1,CERT1,100,1,\r\n'
570            'C2,F1,D1,CERT1,400,0,\r\n'
571            'C3,F1,D2,CERT3,100,0,\r\n'
572            )
573        return
574
575    def test_export_all_to_string(self):
576        # we can export all certificates in a site to a string
577        exporter = CertificateCourseExporter()
578        result = exporter.export_all(self.site, filepath=None)
579        self.assertEqual(
580            result,
581            'course,faculty_code,department_code,certificate_code,'
582            'level,mandatory,course_category\r\n'
583            'C1,F1,D1,CERT1,100,1,\r\n'
584            'C2,F1,D1,CERT1,400,0,\r\n'
585            'C3,F1,D2,CERT3,100,0,\r\n'
586            )
587        return
Note: See TracBrowser for help on using the repository browser.