~ubuntu-branches/ubuntu/wily/spyder/wily

« back to all changes in this revision

Viewing changes to spyderlib/widgets/importwizard.py

  • Committer: Package Import Robot
  • Author(s): Benjamin Drung
  • Date: 2015-01-15 12:20:11 UTC
  • mfrom: (18.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150115122011-cc7j5dhy2h9uo13m
Tags: 2.3.2+dfsg-1ubuntu1
Backport patch to support pylint3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
from functools import partial as ft_partial
24
24
 
 
25
try:
 
26
    import pandas as pd
 
27
except ImportError:
 
28
    pd = None
 
29
 
25
30
# Local import
26
31
from spyderlib.baseconfig import _
27
32
from spyderlib.utils import programs
28
33
from spyderlib.utils.qthelpers import get_icon, add_actions, create_action
29
34
from spyderlib.py3compat import (TEXT_TYPES, INT_TYPES, to_text_string, u,
30
 
                                 zip_longest)
 
35
                                 zip_longest, io)
31
36
 
32
37
def try_to_parse(value):
33
38
    _types = ('int', 'float')
35
40
        try:
36
41
            _val = eval("%s('%s')" % (_t, value))
37
42
            return _val
38
 
        except ValueError:
 
43
        except (ValueError, SyntaxError):
39
44
            pass
40
45
    return value
41
46
 
71
76
def datestr_to_datetime(value, dayfirst=True):
72
77
    return dateparse(value, dayfirst=dayfirst)
73
78
 
74
 
#----Background colors for supported types 
 
79
#----Background colors for supported types
75
80
COLORS = {
76
81
          bool: Qt.magenta,
77
82
          tuple([float] + list(INT_TYPES)): Qt.blue,
96
101
    """Import wizard contents widget"""
97
102
    def __init__(self, parent, text):
98
103
        QWidget.__init__(self, parent)
99
 
        
 
104
 
100
105
        self.text_editor = QTextEdit(self)
101
106
        self.text_editor.setText(text)
102
107
        self.text_editor.setReadOnly(True)
103
 
        
 
108
 
104
109
        # Type frame
105
110
        type_layout = QHBoxLayout()
106
111
        type_label = QLabel(_("Import as"))
111
116
        type_layout.addWidget(data_btn)
112
117
        code_btn = QRadioButton(_("code"))
113
118
        self._as_code = False
114
 
        type_layout.addWidget(code_btn)        
 
119
        type_layout.addWidget(code_btn)
115
120
        txt_btn = QRadioButton(_("text"))
116
121
        type_layout.addWidget(txt_btn)
 
122
 
117
123
        h_spacer = QSpacerItem(40, 20,
118
124
                               QSizePolicy.Expanding, QSizePolicy.Minimum)
119
 
        type_layout.addItem(h_spacer)        
 
125
        type_layout.addItem(h_spacer)
120
126
        type_frame = QFrame()
121
127
        type_frame.setLayout(type_layout)
122
 
        
 
128
 
123
129
        # Opts frame
124
130
        grid_layout = QGridLayout()
125
131
        grid_layout.setSpacing(0)
126
 
        
 
132
 
127
133
        col_label = QLabel(_("Column separator:"))
128
134
        grid_layout.addWidget(col_label, 0, 0)
129
135
        col_w = QWidget()
130
136
        col_btn_layout = QHBoxLayout()
131
137
        self.tab_btn = QRadioButton(_("Tab"))
132
 
        self.tab_btn.setChecked(True)
 
138
        self.tab_btn.setChecked(False)
133
139
        col_btn_layout.addWidget(self.tab_btn)
134
140
        other_btn_col = QRadioButton(_("other"))
 
141
        other_btn_col.setChecked(True)
135
142
        col_btn_layout.addWidget(other_btn_col)
136
143
        col_w.setLayout(col_btn_layout)
137
144
        grid_layout.addWidget(col_w, 0, 1)
138
145
        self.line_edt = QLineEdit(",")
139
146
        self.line_edt.setMaximumWidth(30)
140
 
        self.line_edt.setEnabled(False)
 
147
        self.line_edt.setEnabled(True)
141
148
        self.connect(other_btn_col, SIGNAL("toggled(bool)"),
142
149
                     self.line_edt, SLOT("setEnabled(bool)"))
143
150
        grid_layout.addWidget(self.line_edt, 0, 2)
161
168
        grid_layout.addWidget(self.line_edt_row, 1, 2)
162
169
 
163
170
        grid_layout.setRowMinimumHeight(2, 15)
164
 
        
165
 
        other_group = QGroupBox(_("Additionnal options"))
 
171
 
 
172
        other_group = QGroupBox(_("Additional options"))
166
173
        other_layout = QGridLayout()
167
174
        other_group.setLayout(other_layout)
168
175
 
174
181
                                 self.skiprows_edt)
175
182
        self.skiprows_edt.setValidator(intvalid)
176
183
        other_layout.addWidget(self.skiprows_edt, 0, 1)
177
 
        
 
184
 
178
185
        other_layout.setColumnMinimumWidth(2, 5)
179
 
        
 
186
 
180
187
        comments_label = QLabel(_("Comments:"))
181
188
        other_layout.addWidget(comments_label, 0, 3)
182
189
        self.comments_edt = QLineEdit('#')
183
190
        self.comments_edt.setMaximumWidth(30)
184
191
        other_layout.addWidget(self.comments_edt, 0, 4)
185
 
        
 
192
 
186
193
        self.trnsp_box = QCheckBox(_("Transpose"))
187
194
        #self.trnsp_box.setEnabled(False)
188
195
        other_layout.addWidget(self.trnsp_box, 1, 0, 2, 0)
189
 
        
 
196
 
190
197
        grid_layout.addWidget(other_group, 3, 0, 2, 0)
191
 
        
 
198
 
192
199
        opts_frame = QFrame()
193
200
        opts_frame.setLayout(grid_layout)
194
 
        
 
201
 
195
202
        self.connect(data_btn, SIGNAL("toggled(bool)"),
196
203
                     opts_frame, SLOT("setEnabled(bool)"))
197
204
        self.connect(data_btn, SIGNAL("toggled(bool)"),
211
218
    def get_as_data(self):
212
219
        """Return if data type conversion"""
213
220
        return self._as_data
214
 
    
 
221
 
215
222
    def get_as_code(self):
216
223
        """Return if code type conversion"""
217
224
        return self._as_code
218
 
    
 
225
 
219
226
    def get_as_num(self):
220
227
        """Return if numeric type conversion"""
221
228
        return self._as_num
225
232
        if self.tab_btn.isChecked():
226
233
            return u("\t")
227
234
        return to_text_string(self.line_edt.text())
228
 
    
 
235
 
229
236
    def get_row_sep(self):
230
237
        """Return the row separator"""
231
238
        if self.eol_btn.isChecked():
232
239
            return u("\n")
233
240
        return to_text_string(self.line_edt_row.text())
234
 
    
 
241
 
235
242
    def get_skiprows(self):
236
243
        """Return number of lines to be skipped"""
237
244
        return int(to_text_string(self.skiprows_edt.text()))
238
 
    
 
245
 
239
246
    def get_comments(self):
240
247
        """Return comment string"""
241
248
        return to_text_string(self.comments_edt.text())
251
258
        """Set if code type conversion"""
252
259
        self._as_code = as_code
253
260
 
 
261
 
254
262
class PreviewTableModel(QAbstractTableModel):
255
263
    """Import wizard preview table model"""
256
264
    def __init__(self, data=[], parent=None):
260
268
    def rowCount(self, parent=QModelIndex()):
261
269
        """Return row count"""
262
270
        return len(self._data)
263
 
    
 
271
 
264
272
    def columnCount(self, parent=QModelIndex()):
265
273
        """Return column count"""
266
274
        return len(self._data[0])
268
276
    def _display_data(self, index):
269
277
        """Return a data element"""
270
278
        return to_qvariant(self._data[index.row()][index.column()])
271
 
    
 
279
 
272
280
    def data(self, index, role=Qt.DisplayRole):
273
281
        """Return a model data element"""
274
282
        if not index.isValid():
276
284
        if role == Qt.DisplayRole:
277
285
            return self._display_data(index)
278
286
        elif role == Qt.BackgroundColorRole:
279
 
            return to_qvariant(get_color(self._data[index.row()][index.column()], .2))            
 
287
            return to_qvariant(get_color(self._data[index.row()][index.column()], .2))
280
288
        elif role == Qt.TextAlignmentRole:
281
289
            return to_qvariant(int(Qt.AlignRight|Qt.AlignVCenter))
282
290
        return to_qvariant()
283
 
    
 
291
 
284
292
    def setData(self, index, value, role=Qt.EditRole):
285
293
        """Set model data"""
286
294
        return False
312
320
                    self._data[index.row()][index.column()])
313
321
            elif kwargs['atype'] == "float":
314
322
                self._data[index.row()][index.column()] = float(
315
 
                    self._data[index.row()][index.column()])                
 
323
                    self._data[index.row()][index.column()])
316
324
            self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
317
325
        except Exception as instance:
318
326
            print(instance)
338
346
            triggered=ft_partial(self.parse_to_type, atype="int"))
339
347
        self.float_action = create_action(self, "float",
340
348
            triggered=ft_partial(self.parse_to_type, atype="float"))
341
 
        
 
349
 
342
350
        # Setting up menus
343
351
        self.date_menu = QMenu()
344
352
        self.date_menu.setTitle("Date")
377
385
        if transpose:
378
386
            return [[r[col] for r in out] for col in range(len(out[0]))]
379
387
        return out
380
 
    
 
388
 
381
389
    def get_data(self):
382
390
        """Return model data"""
383
391
        if self._model is None:
398
406
        if not indexes: return
399
407
        for index in indexes:
400
408
            self.model().parse_data_type(index, **kwargs)
401
 
    
 
409
 
402
410
    def contextMenuEvent(self, event):
403
411
        """Reimplement Qt method"""
404
412
        self.opt_menu.popup(event.globalPos())
406
414
 
407
415
class PreviewWidget(QWidget):
408
416
    """Import wizard preview widget"""
409
 
    
 
417
 
410
418
    def __init__(self, parent):
411
419
        QWidget.__init__(self, parent)
412
 
        
 
420
 
413
421
        vert_layout = QVBoxLayout()
414
 
        
 
422
 
415
423
        # Type frame
416
424
        type_layout = QHBoxLayout()
417
425
        type_label = QLabel(_("Import as"))
418
426
        type_layout.addWidget(type_label)
 
427
 
419
428
        self.array_btn = array_btn = QRadioButton(_("array"))
420
429
        array_btn.setEnabled(ndarray is not FakeObject)
421
430
        array_btn.setChecked(ndarray is not FakeObject)
422
 
 
423
431
        type_layout.addWidget(array_btn)
 
432
 
424
433
        list_btn = QRadioButton(_("list"))
425
434
        list_btn.setChecked(not array_btn.isChecked())
426
 
        type_layout.addWidget(list_btn)    
 
435
        type_layout.addWidget(list_btn)
 
436
 
 
437
        if pd:
 
438
            self.df_btn = df_btn = QRadioButton(_("DataFrame"))
 
439
            df_btn.setChecked(False)
 
440
            type_layout.addWidget(df_btn)
 
441
 
427
442
        h_spacer = QSpacerItem(40, 20,
428
443
                               QSizePolicy.Expanding, QSizePolicy.Minimum)
429
 
        type_layout.addItem(h_spacer)        
 
444
        type_layout.addItem(h_spacer)
430
445
        type_frame = QFrame()
431
446
        type_frame.setLayout(type_layout)
432
 
        
 
447
 
433
448
        self._table_view = PreviewTable(self)
434
449
        vert_layout.addWidget(type_frame)
435
450
        vert_layout.addWidget(self._table_view)
438
453
    def open_data(self, text, colsep=u("\t"), rowsep=u("\n"),
439
454
                  transpose=False, skiprows=0, comments='#'):
440
455
        """Open clipboard text as table"""
 
456
        if pd:
 
457
            self.pd_text = text
 
458
            self.pd_info = dict(sep=colsep, lineterminator=rowsep,
 
459
                skiprows=skiprows,comment=comments)
441
460
        self._table_view.process_data(text, colsep, rowsep, transpose,
442
461
                                      skiprows, comments)
443
 
    
 
462
 
444
463
    def get_data(self):
445
464
        """Return table data"""
446
465
        return self._table_view.get_data()
450
469
    def __init__(self, parent, text,
451
470
                 title=None, icon=None, contents_title=None, varname=None):
452
471
        QDialog.__init__(self, parent)
453
 
        
 
472
 
454
473
        # Destroying the C++ object right after closing the dialog box,
455
474
        # otherwise it may be garbage-collected in another QThread
456
475
        # (e.g. the editor's analysis thread in Spyder), thus leading to
457
476
        # a segmentation fault on UNIX or an application crash on Windows
458
477
        self.setAttribute(Qt.WA_DeleteOnClose)
459
 
        
 
478
 
460
479
        if title is None:
461
480
            title = _("Import wizard")
462
481
        self.setWindowTitle(title)
464
483
            self.setWindowIcon(get_icon("fileimport.png"))
465
484
        if contents_title is None:
466
485
            contents_title = _("Raw text")
467
 
        
 
486
 
468
487
        if varname is None:
469
488
            varname = _("variable_name")
470
 
        
 
489
 
471
490
        self.var_name, self.clip_data = None, None
472
 
        
 
491
 
473
492
        # Setting GUI
474
493
        self.tab_widget = QTabWidget(self)
475
494
        self.text_widget = ContentsWidget(self, text)
476
495
        self.table_widget = PreviewWidget(self)
477
 
        
 
496
 
478
497
        self.tab_widget.addTab(self.text_widget, _("text"))
479
498
        self.tab_widget.setTabText(0, contents_title)
480
499
        self.tab_widget.addTab(self.table_widget, _("table"))
481
500
        self.tab_widget.setTabText(1, _("Preview"))
482
501
        self.tab_widget.setTabEnabled(1, False)
483
 
        
 
502
 
484
503
        name_layout = QHBoxLayout()
485
504
        name_label = QLabel(_("Variable Name"))
486
505
        name_layout.addWidget(name_label)
487
 
        
 
506
 
488
507
        self.name_edt = QLineEdit()
489
508
        self.name_edt.setText(varname)
490
509
        name_layout.addWidget(self.name_edt)
491
 
        
 
510
 
492
511
        btns_layout = QHBoxLayout()
493
512
        cancel_btn = QPushButton(_("Cancel"))
494
513
        btns_layout.addWidget(cancel_btn)
510
529
        btns_layout.addWidget(self.done_btn)
511
530
        self.connect(self.done_btn, SIGNAL("clicked()"),
512
531
                     self, SLOT("process()"))
513
 
        
 
532
 
514
533
        self.connect(self.text_widget, SIGNAL("asDataChanged(bool)"),
515
534
                     self.fwd_btn, SLOT("setEnabled(bool)"))
516
535
        self.connect(self.text_widget, SIGNAL("asDataChanged(bool)"),
527
546
            self.tab_widget.setTabEnabled(i, False)
528
547
        self.tab_widget.setTabEnabled(tab_idx, True)
529
548
        self.tab_widget.setCurrentIndex(tab_idx)
530
 
        
 
549
 
531
550
    def _set_step(self, step):
532
551
        """Proceed to a given step"""
533
552
        new_tab = self.tab_widget.currentIndex() + step
555
574
            self.fwd_btn.setEnabled(True)
556
575
            self.back_btn.setEnabled(False)
557
576
        self._focus_tab(new_tab)
558
 
    
 
577
 
559
578
    def get_data(self):
560
579
        """Return processed data"""
561
580
        # It is import to avoid accessing Qt C++ object as it has probably
578
597
                self.table_widget.get_data())
579
598
        if self.table_widget.array_btn.isChecked():
580
599
            return array(data)
 
600
        elif pd and self.table_widget.df_btn.isChecked():
 
601
            info = self.table_widget.pd_info
 
602
            buf = io.StringIO(self.table_widget.pd_text)
 
603
            return pd.read_csv(buf, **info)
581
604
        return data
582
605
 
583
606
    def _get_plain_text(self):