source: main/waeup.sirp/branches/ulif-fasttables/src/waeup/sirp/jambtables/jambtables.py @ 5242

Last change on this file since 5242 was 5242, checked in by uli, 14 years ago

Add accessor methods for JAMB tables.

File size: 5.0 KB
Line 
1##
2## jambtables.py
3## Login : <uli@pu.smp.net>
4## Started on  Tue Jun 22 06:31:42 2010 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2010 Uli Fouquet
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22import csv
23import os
24import shutil
25import tempfile
26import grok
27
28from datetime import datetime
29from BTrees.OOBTree import OOBTree
30from BTrees.Length import Length
31
32def filter_data(datadict):
33    """Filter items whose key contains 'ignore'
34    """
35    keys = datadict.keys()
36    for key in keys:
37        if not 'ignore' in key:
38            continue
39        del datadict[key]
40    for name in ['firstname', 'lastname', 'middlenames', 'screening_type',
41                 'screening_venue', 'reg_no', 'sex', 'course1', 'jamb_state',
42                 'screening_date', 'jamb_lga', 'fst_sit_fname',]:
43        datadict[name] = unicode(datadict[name])
44    datadict['date_of_birth'] = datetime.strptime(
45        datadict['date_of_birth'],
46        '%d/%m/%Y'
47        ).date()
48   
49    return datadict
50
51
52class JAMBDataTable(grok.Model):
53    """A data table that contains JAMB data.
54
55    JAMB data tables are plain but fast as they store nearly no data
56    inside the ZODB. All data is held on-disk in CSV tables.
57
58    As a consequence these tables are read-only.
59    """
60
61    import_datetime = None
62   
63    def __init__(self):
64        super(JAMBDataTable, self).__init__()
65        self._datafile_path = None
66        self._data_len = 0
67        self._temporary = False
68        return
69
70    def __del__(self):
71        self.clear()
72
73    def __iter__(self):
74        reader = None
75        if self._datafile_path is not None:
76            reader = csv.DictReader(open(self._datafile_path, 'rb'))
77        if reader is None:
78            raise StopIteration
79        for line in reader:
80            data_dict = filter_data(line)
81            yield data_dict
82
83    def keys(self):
84        """Get iterator over all registration numbers stored in table.
85        """
86        for item in self:
87            yield item['reg_no']
88
89    def items(self):
90        """Get tuples of registration number and datasets for each entry in
91           data table.
92        """
93        for item in self:
94            yield (item['reg_no'], item)
95           
96    def clear(self):
97        """Remove all existing entries.
98        """
99        self.import_datetime = None
100        if self._datafile_path is None:
101            return
102        if self._temporary:
103            if not os.path.exists(self._datafile_path):
104                return
105            shutil.rmtree(os.path.dirname(self._datafile_path))
106        self._datafile_path = None
107           
108    def importFromCSV(self, filepath):
109        """Importing data from a CSV file means to copy the source to a safe
110           location.
111        """
112        self.clear()
113        self.import_datetime = datetime.now()
114        self._copyDataFile(filepath)
115
116    #def add(self, reg_no, data_dict):
117    #    item = filter_data(data_dict)
118    #    item.__name__ = reg_no
119    #    item.__parent__ = self
120    #    #if send_events:
121    #    #    objectEventNotify(ObjectWillBeAddedEvent(item, self, reg_no))
122    #    #self._data[reg_no] = item
123    #    self._data_len += 1
124    #    #if senf_event:
125    #    #    objectEventNotify(ObjectAddedEvent(item, self, reg_no))
126
127    def _copyDataFile(self, path):
128        """Copy file in path to the JAMBData storage.
129
130        See :meth:`_getJAMBTableStorage`.
131        """
132        storage = self._getJAMBTableStorage()
133        self._datafile_path = os.path.join(
134            storage, os.path.basename(path)
135            )
136        shutil.copy2(path, self._datafile_path)
137        return
138
139    def _getJAMBTableStorage(self):
140        """Get a path to store copies of datatables.
141
142        We normally store data in a ``jambdata`` subdir of datacenter,
143        but if none exists, we create a temporary dir and set
144        `temporary` to ``True``.
145
146        Any not existent directory is created.
147
148        Note, that temporary dirs will be deleted when the
149        JAMBDataTable object is destroyed.
150
151        Returns absolute path to the JAMB data storage.
152        """
153        site = grok.getSite()
154        if site is None:
155            jambtable_storage = tempfile.mkdtemp()
156            self._temporary = True
157        else:
158            datacenter = site['datacenter']
159            jambtable_storage = os.path.join(datacenter.storage, 'jambdata')
160        if not os.path.isdir(jambtable_storage):
161            os.mkdir(jambtable_storage)
162        return os.path.abspath(jambtable_storage)
Note: See TracBrowser for help on using the repository browser.