~launchpad-p-s/sofastatistics/main

« back to all changes in this revision

Viewing changes to getdata.py

  • Committer: Grant Paton-Simpson
  • Date: 2009-05-19 04:21:43 UTC
  • Revision ID: g@ubuntu-20090519042143-p561mbokz3inefvd
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
import pprint
 
3
import wx
 
4
 
 
5
import util
 
6
 
 
7
# must be before dbe import statements (they have classes based on DbDets)
 
8
class DbDets(object):
 
9
    
 
10
    def __init__ (self, conn_dets, db=None, tbl=None):
 
11
        self.conn_dets = conn_dets
 
12
        self.db = db
 
13
        self.tbl = tbl
 
14
    
 
15
    def getDbTbls(self, cur, db):
 
16
        "Must return tbls"
 
17
        assert 0, "Must define getDbTbls in subclass"
 
18
        
 
19
    def getTblFlds(self, cur, db, tbl):
 
20
        """
 
21
        Must return dic of dics called flds.
 
22
        Gets dic of dics for each field with field name as key. Each field dic
 
23
            has as keys the FLD_ variables listed below e.g. FLD_BOLNUMERIC.
 
24
        Need enough to present fields in order, validate data entry, 
 
25
            and guide labelling and reporting (e.g. numeric or categorical).
 
26
        """
 
27
        assert 0, "Must define getTblFlds in subclass"
 
28
    
 
29
    def getIndexDets(self, cur, db, tbl):
 
30
        "Must return has_unique, idxs"
 
31
        assert 0, "Must define getIndexDets in subclass"
 
32
       
 
33
    def getDbDets(self):
 
34
        "Must return conn, cur, dbs, tbls, flds"
 
35
        assert 0, "Must define getDbDets in subclass"
 
36
 
 
37
"""
 
38
Include database engine in system if in dbe_plugins folder and os-appropriate.
 
39
"""
 
40
# also used as labels in dropdowns
 
41
DBE_SQLITE = "SQLite"
 
42
DBE_MYSQL = "MySQL"
 
43
DBE_MS_ACCESS = "MS Access"
 
44
def import_dbe_plugin(dbe_plugin):
 
45
    if dbe_plugin == DBE_SQLITE:
 
46
        import dbe_plugins.dbe_sqlite as dbe_sqlite
 
47
        mod = dbe_sqlite
 
48
    elif dbe_plugin == DBE_MYSQL:
 
49
        import dbe_plugins.dbe_mysql as dbe_mysql
 
50
        mod = dbe_mysql
 
51
    elif dbe_plugin == DBE_MS_ACCESS:
 
52
        import dbe_plugins.dbe_ms_access as dbe_ms_access
 
53
        mod = dbe_ms_access
 
54
    return mod
 
55
DBES = []
 
56
DBE_MODULES = {}
 
57
DBE_PLUGINS = [(DBE_SQLITE, "dbe_sqlite"), (DBE_MYSQL, "dbe_mysql"), 
 
58
               (DBE_MS_ACCESS, "dbe_ms_access")]
 
59
for dbe_plugin, dbe_mod_name in DBE_PLUGINS:
 
60
    dbe_plugin_mod = os.path.join(util.get_script_path(), "dbe_plugins", 
 
61
                                   "%s.py" % dbe_mod_name)
 
62
    if os.path.exists(dbe_plugin_mod):
 
63
        if not (not util.in_windows() and dbe_plugin == DBE_MS_ACCESS):
 
64
            DBES.append(dbe_plugin)
 
65
            dbe_mod = import_dbe_plugin(dbe_plugin)
 
66
            DBE_MODULES[dbe_plugin] = dbe_mod
 
67
# misc field dets
 
68
FLD_SEQ = "field sequence"
 
69
FLD_BOLNULLABLE = "field nullable"
 
70
FLD_DATA_ENTRY_OK = "data entry ok" # e.g. not autonumber, timestamp etc
 
71
FLD_COLUMN_DEFAULT = "field default"
 
72
# test
 
73
FLD_BOLTEXT = "field text"
 
74
FLD_TEXT_LENGTH = "field text length"
 
75
FLD_CHARSET = "field charset"
 
76
# numbers
 
77
FLD_BOLNUMERIC = "field numeric"
 
78
FLD_BOLAUTONUMBER = "field autonumber"
 
79
FLD_DECPTS = "field decpts"
 
80
FLD_NUM_WIDTH = "field numeric display width" # used for column display only
 
81
FLD_BOL_NUM_SIGNED = "field numeric signed"
 
82
FLD_NUM_MIN_VAL = "field numeric minimum value"
 
83
FLD_NUM_MAX_VAL = "field numeric maximum value"
 
84
# datetime
 
85
FLD_BOLDATETIME = "field datetime"
 
86
# indexes
 
87
IDX_NAME = "index name"
 
88
IDX_IS_UNIQUE = "index is unique"
 
89
IDX_FLDS = "index fields"
 
90
 
 
91
def getDbDetsObj(dbe, conn_dets, db, tbl):
 
92
    return DBE_MODULES[dbe].DbDets(conn_dets, db, tbl)
 
93
 
 
94
def getDbeSyntaxElements(dbe):
 
95
    """
 
96
    Returns if_clause, abs_wrapper_l, abs_wrapper_r - all strings.
 
97
    if_clause receives 3 inputs - the test, result if true, result if false
 
98
    e.g. MySQL "IF(%s, %s, %s)"
 
99
    """
 
100
    return DBE_MODULES[dbe].DbeSyntaxElements()
 
101
 
 
102
def setDataConnGui(parent, read_only, scroll, szr, lblfont):
 
103
    ""
 
104
    for dbe in DBES:
 
105
        DBE_MODULES[dbe].setDataConnGui(parent, read_only, scroll, szr, 
 
106
                                        lblfont)
 
107
 
 
108
def getProjConnSettings(parent, proj_dic):
 
109
    "Get project connection settings"
 
110
    for dbe in DBES:
 
111
        DBE_MODULES[dbe].getProjSettings(parent, proj_dic)
 
112
 
 
113
def FldsDic2FldNamesLst(flds_dic):
 
114
    # pprint.pprint(flds_dic) # debug
 
115
    flds_lst = sorted(flds_dic, key=lambda s: flds_dic[s][FLD_SEQ])
 
116
    return flds_lst
 
117
 
 
118
def setConnDetDefaults(parent):
 
119
    """
 
120
    Check project connection settings to handle missing values and set 
 
121
        sensible defaults.
 
122
    """
 
123
    for dbe in DBES:
 
124
        DBE_MODULES[dbe].setConnDetDefaults(parent)
 
125
 
 
126
def processConnDets(parent, default_dbs, default_tbls, conn_dets):
 
127
    """
 
128
    Populate default_dbs, default_tbls, conn_dets.
 
129
    Returns any_incomplete (partially completed connection details), 
 
130
        any_conns (any of them set completely), and completed_dbes.
 
131
        Completed_dbes is so we can ensure the default dbe has conn details 
 
132
        set for it.
 
133
    NB If any incomplete, stop processing and return None for any_conns.
 
134
    """
 
135
    any_incomplete = False
 
136
    any_conns = False
 
137
    completed_dbes = [] # so can check the default dbe has details set
 
138
    for dbe in DBES:
 
139
        # has_incomplete means started but some key detail(s) missing
 
140
        # has_conn means all required details are completed
 
141
        has_incomplete, has_conn = \
 
142
            DBE_MODULES[dbe].processConnDets(parent, default_dbs, 
 
143
                                             default_tbls, conn_dets)
 
144
        if has_incomplete:
 
145
            return True, None
 
146
        if has_conn:
 
147
            completed_dbes.append(dbe)
 
148
            any_conns = True
 
149
    return any_incomplete, any_conns, completed_dbes
 
150
 
 
151
def getDbItem(db_name, dbe):
 
152
    return "%s (%s)" % (db_name, dbe)
 
153
 
 
154
def extractDbDets(choice_text):
 
155
    start_idx = choice_text.index("(") + 1
 
156
    end_idx = choice_text.index(")")
 
157
    dbe = choice_text[start_idx:end_idx]
 
158
    db_name = choice_text[:start_idx - 2]
 
159
    return db_name, dbe
 
160
 
 
161
def InsertRow(dbe, conn, cur, tbl_name, data):
 
162
    """
 
163
    data = [(value as string, fld_dets), ...]
 
164
    """
 
165
    return DBE_MODULES[dbe].InsertRow(conn, cur, tbl_name, data)
 
166
 
 
167
def setupDataDropdowns(parent, panel, dbe, conn_dets, default_dbs, 
 
168
                       default_tbls):
 
169
    """
 
170
    Sets up frame with the following properties: dbe, conn_dets, conn, cur, 
 
171
        default_dbs, default_db (possibly None), db (default db if possible), 
 
172
        db_choice_items, tbls (for selected db), default_tbl, 
 
173
        and tbl_name (default if possible).  Plus flds, has_unique and idxs.
 
174
    Adds dropDatabases and dropTables to frame with correct values 
 
175
        and default selection.
 
176
    """    
 
177
    parent.dbe = dbe
 
178
    parent.conn_dets = conn_dets
 
179
    parent.default_dbs = default_dbs
 
180
    if not parent.default_dbs:
 
181
        parent.default_dbs = []
 
182
        default_db = None
 
183
    else:
 
184
        default_db = parent.default_dbs.get(parent.dbe)
 
185
    parent.default_tbls = default_tbls
 
186
    if not default_tbls:
 
187
        parent.default_tbls = []
 
188
        parent.default_tbl = None
 
189
    else:
 
190
        parent.default_tbl = parent.default_tbls.get(parent.dbe)
 
191
    # for default dbe, get default tbl (or first) and its fields
 
192
    # for each other dbe, need to get database details to add to list
 
193
    parent.conn, parent.cur, default_dbe_dbs, parent.tbls, parent.flds, \
 
194
            parent.has_unique, parent.idxs = \
 
195
        getDbDetsObj(parent.dbe, parent.conn_dets, db=default_db, 
 
196
                     tbl=parent.default_tbl).getDbDets()
 
197
    # databases list needs to be tuple including dbe so can get both from 
 
198
    # sequence alone e.g. when identifying selection
 
199
    db_choices = [(x, parent.dbe) for x in default_dbe_dbs]      
 
200
    dbes = DBES[:]
 
201
    dbes.pop(dbes.index(parent.dbe))
 
202
    for oth_dbe in dbes: # may not have any connection details
 
203
        oth_default_db = parent.default_dbs.get(oth_dbe)
 
204
        dbdetsobj = getDbDetsObj(oth_dbe, parent.conn_dets, 
 
205
                                 oth_default_db, None)
 
206
        try:
 
207
            _, _, oth_dbs, _, _, _, _ = dbdetsobj.getDbDets()
 
208
            oth_db_choices = [(x, oth_dbe) for x in oth_dbs]
 
209
            db_choices.extend(oth_db_choices)
 
210
        except Exception, e:
 
211
            print str(e)
 
212
            pass # no connection possible            
 
213
    parent.db = default_db if default_db else default_dbe_dbs[0]
 
214
    parent.tbl_name = parent.default_tbl if parent.default_tbl \
 
215
        else parent.tbls[0]
 
216
    parent.db_choice_items = [getDbItem(x[0], x[1]) for x in db_choices]
 
217
    parent.dropDatabases = wx.Choice(panel, -1, 
 
218
                                     choices=parent.db_choice_items)
 
219
    if default_db:
 
220
        # should be correct index if same sort order on choice items 
 
221
        # as db list
 
222
        dbs = [x[0] for x in db_choices]
 
223
        try:
 
224
            parent.dropDatabases.SetSelection(dbs.index(default_db))
 
225
        except Exception:
 
226
            pass # perhaps the default table is not in the default database ;-)
 
227
    else:
 
228
        # first database of default dbe (which was always first)
 
229
        parent.dropDatabases.SetSelection(n=0)
 
230
    parent.dropTables = wx.Choice(panel, -1, choices=parent.tbls)
 
231
    try:
 
232
        idx_default_tbl = parent.tbls.index(parent.default_tbl)
 
233
        parent.dropTables.SetSelection(idx_default_tbl)
 
234
    except Exception:
 
235
        parent.dropTables.SetSelection(n=0)
 
236
 
 
237
def ResetDataAfterDbSel(parent):
 
238
    """
 
239
    Reset dbe, database, cursor, tables, table, tables dropdown, 
 
240
        fields, has_unique, and idxs after a database selection.
 
241
    """
 
242
    db_choice_item = parent.db_choice_items[parent.dropDatabases.GetSelection()]
 
243
    db_name, dbe = extractDbDets(db_choice_item)
 
244
    parent.dbe = dbe
 
245
    parent.db = db_name
 
246
    default_tbl = parent.default_tbls.get(parent.dbe) 
 
247
    # for default dbe, get default tbl (or first) and its fields
 
248
    # for each other dbe, need to get database details to add to list
 
249
    dbdetsobj = getDbDetsObj(parent.dbe, parent.conn_dets, db=db_name, 
 
250
                             tbl=default_tbl)
 
251
    parent.conn, parent.cur, sel_dbe_dbs, parent.tbls, parent.flds, \
 
252
            parent.has_unique, parent.idxs = \
 
253
        dbdetsobj.getDbDets()
 
254
    default_tbl = parent.tbls[0] # default condition
 
255
    if parent.default_tbls and parent.default_dbs:
 
256
        if parent.db == parent.default_dbs[parent.dbe]:
 
257
            default_tbl = parent.default_tbls.get(parent.dbe)
 
258
    parent.tbl_name = default_tbl
 
259
    parent.dropTables.SetItems(parent.tbls)
 
260
    parent.dropTables.SetSelection(parent.tbls.index(default_tbl))
 
261
    parent.flds = dbdetsobj.getTblFlds(parent.cur, parent.db, parent.tbl_name)
 
262
 
 
263
def ResetDataAfterTblSel(parent):
 
264
    "Reset table, fields, has_unique, and idxs after a table selection."
 
265
    parent.tbl_name = parent.tbls[parent.dropTables.GetSelection()]
 
266
    dbdetsobj = getDbDetsObj(parent.dbe, parent.conn_dets, parent.db, 
 
267
                             parent.tbl_name)
 
268
    parent.flds = dbdetsobj.getTblFlds(parent.cur, parent.db, parent.tbl_name)
 
269
    parent.has_unique, parent.idxs = dbdetsobj.getIndexDets(parent.cur, 
 
270
                                                parent.db, parent.tbl_name)    
 
271
    
 
 
b'\\ No newline at end of file'