source: main/waeup.sirp/branches/ulif-schoolgrades/src/waeup/sirp/university/export.py @ 7768

Last change on this file since 7768 was 7757, checked in by Henrik Bettermann, 13 years ago

Add copyright header and svn keyword.

  • Property svn:keywords set to Id
File size: 9.0 KB
Line 
1## $Id: export.py 7757 2012-03-03 06:02:36Z 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##
18"""Exporters for faculties, departments, and other academics components.
19"""
20import csv
21import grok
22from cStringIO import StringIO
23from waeup.sirp.interfaces import ICSVExporter
24
25class FacultyExporter(grok.GlobalUtility):
26    """Exporter for faculties.
27    """
28    grok.implements(ICSVExporter)
29    grok.name('faculties')
30
31    #: Fieldnames considered by this exporter
32    fields = ('code', 'title', 'title_prefix')
33
34    def mangle_value(self, value, name, context=None):
35        """Hook for mangling values in derived classes
36        """
37        if isinstance(value, bool):
38            value = value and '1' or '0'
39        elif isinstance(value, unicode):
40            # CSV writers like byte streams better than unicode
41            value = value.encode('utf-8')
42        elif value is None:
43            # None is not really representable in CSV files
44            value = ''
45        return value
46
47    def get_csv_writer(self, filepath=None):
48        """Get a CSV dict writer instance open for writing.
49
50        Returns a tuple (<writer>, <outfile>) where ``<writer>`` is a
51        :class:`csv.DictWriter` instance and outfile is the real file
52        which is written to. The latter is important when writing to
53        StringIO and can normally be ignored otherwise.
54
55        The returned file will already be filled with the header row.
56        """
57        if filepath is None:
58            outfile = StringIO()
59        else:
60            outfile = open(filepath, 'wb')
61        writer = csv.DictWriter(outfile, self.fields)
62        writer.writerow(dict(zip(self.fields, self.fields))) # header
63        return writer, outfile
64
65    def write_item(self, faculty, writer):
66        """Write a row into using `writer`.
67        """
68        row = {}
69        for name in self.fields:
70            value = getattr(faculty, name, None)
71            value = self.mangle_value(value, name, faculty)
72            row[name] = value
73        writer.writerow(row)
74        return
75
76    def close_outfile(self, filepath, outfile):
77        """Close outfile.
78
79        If filepath is None, the contents of outfile is returned.
80        """
81        outfile.seek(0)
82        if filepath is None:
83            return outfile.read()
84        outfile.close()
85        return
86
87    def export(self, faculties, filepath=None):
88        """Export `faculties`, an iterable, as CSV file.
89
90        If `filepath` is ``None``, a raw string with CSV data is returned.
91        """
92        writer, outfile = self.get_csv_writer(filepath)
93        for faculty in faculties:
94            self.write_item(faculty, writer)
95        return self.close_outfile(filepath, outfile)
96
97    def export_all(self, site, filepath=None):
98        """Export faculties in facultycontainer into filepath as CSV data.
99
100        If `filepath` is ``None``, a raw string with CSV data is returned.
101        """
102        writer, outfile = self.get_csv_writer(filepath)
103        faculties = site.get('faculties', {})
104        return self.export(faculties.values(), filepath)
105        for faculty in faculties.values():
106            self.write_item(faculty, writer)
107        return self.close_outfile(filepath, outfile)
108
109class DepartmentExporter(FacultyExporter, grok.GlobalUtility):
110    """Exporter for departments.
111    """
112    grok.implements(ICSVExporter)
113    grok.name('departments')
114
115    #: Fieldnames considered by this exporter
116    fields = ('code', 'faculty_code', 'title', 'title_prefix')
117
118    def mangle_value(self, value, name, context=None):
119        """Hook for mangling values in derived classes
120        """
121        if name == 'faculty_code':
122            value = getattr(
123                getattr(context, '__parent__', None),
124                'code', None)
125        return super(DepartmentExporter, self).mangle_value(
126            value, name, context)
127
128    def export_all(self, site, filepath=None):
129        """Export faculties in facultycontainer into filepath as CSV data.
130
131        If `filepath` is ``None``, a raw string with CSV data is returned.
132        """
133        writer, outfile = self.get_csv_writer(filepath)
134        faculties = site.get('faculties', {})
135        for faculty in faculties.values():
136            for department in faculty.values():
137                self.write_item(department, writer)
138        return self.close_outfile(filepath, outfile)
139
140
141class CourseExporter(FacultyExporter, grok.GlobalUtility):
142    """Exporter for courses.
143    """
144    grok.implements(ICSVExporter)
145    grok.name('courses')
146
147    #: Fieldnames considered by this exporter
148    fields = ('code', 'faculty_code', 'department_code', 'title', 'credits',
149              'passmark', 'semester')
150
151    def mangle_value(self, value, name, context=None):
152        """Hook for mangling values in derived classes
153        """
154        if name == 'faculty_code':
155            try:
156                value = context.__parent__.__parent__.__parent__.code
157            except AttributeError:
158                value = None
159        elif name == 'department_code':
160            try:
161                value = context.__parent__.__parent__.code
162            except AttributeError:
163                value = None
164        return super(CourseExporter, self).mangle_value(
165            value, name, context)
166
167    def export_all(self, site, filepath=None):
168        """Export faculties in facultycontainer into filepath as CSV data.
169
170        If `filepath` is ``None``, a raw string with CSV data is returned.
171        """
172        writer, outfile = self.get_csv_writer(filepath)
173        faculties = site.get('faculties', {})
174        for faculty in faculties.values():
175            for department in faculty.values():
176                for course in department.courses.values():
177                    self.write_item(course, writer)
178        return self.close_outfile(filepath, outfile)
179
180class CertificateExporter(CourseExporter, grok.GlobalUtility):
181    """Exporter for courses.
182    """
183    grok.implements(ICSVExporter)
184    grok.name('certificates')
185
186    #: Fieldnames considered by this exporter
187    fields = ('code', 'faculty_code', 'department_code', 'title', 'study_mode',
188              'start_level', 'end_level', 'application_category')
189
190    def export_all(self, site, filepath=None):
191        """Export faculties in facultycontainer into filepath as CSV data.
192
193        If `filepath` is ``None``, a raw string with CSV data is returned.
194        """
195        writer, outfile = self.get_csv_writer(filepath)
196        faculties = site.get('faculties', {})
197        for faculty in faculties.values():
198            for department in faculty.values():
199                for cert in department.certificates.values():
200                    self.write_item(cert, writer)
201        return self.close_outfile(filepath, outfile)
202
203class CertificateCourseExporter(CourseExporter, grok.GlobalUtility):
204    """Exporter for courses.
205    """
206    grok.implements(ICSVExporter)
207    grok.name('certificate_courses')
208
209    #: Fieldnames considered by this exporter
210    fields = ('course', 'faculty_code', 'department_code', 'certificate_code',
211              'level', 'mandatory')
212
213    def mangle_value(self, value, name, context=None):
214        """Hook for mangling values in derived classes
215        """
216        if name == 'faculty_code':
217            try:
218                value = context.__parent__.__parent__.__parent__.__parent__.code
219            except AttributeError:
220                value = None
221        elif name == 'department_code':
222            try:
223                value = context.__parent__.__parent__.__parent__.code
224            except AttributeError:
225                value = None
226        elif name == 'certificate_code':
227            value = getattr(context, '__parent__', None)
228            value = getattr(value, 'code', None)
229        if name == 'course':
230            value = getattr(value, 'code', None)
231        return super(CourseExporter, self).mangle_value(
232            value, name, context)
233
234    def export_all(self, site, filepath=None):
235        """Export faculties in facultycontainer into filepath as CSV data.
236
237        If `filepath` is ``None``, a raw string with CSV data is returned.
238        """
239        writer, outfile = self.get_csv_writer(filepath)
240        faculties = site.get('faculties', {})
241        for faculty in faculties.values():
242            for department in faculty.values():
243                for cert in department.certificates.values():
244                    for certref in cert.values():
245                        self.write_item(certref, writer)
246        return self.close_outfile(filepath, outfile)
Note: See TracBrowser for help on using the repository browser.