Ignore:
Timestamp:
04/18/12 17:31:05 (2 years ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Fixed storing file format hints. Code style fixup.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeWidgets/Prototypes/OWCSVFileImport.py

    r10648 r10814  
    11""" 
    22<name>CSV File import</name> 
    3 <description>Import .csv file</description> 
     3<description>Import comma separated file</description> 
    44 
    55""" 
     
    88from StringIO import StringIO 
    99 
    10 from PyQt4 import QtCore, QtGui 
     10import Orange 
    1111 
    1212from OWWidget import * 
    1313import OWGUI 
    14 import Orange 
    1514 
    1615MakeStatus = Orange.feature.Descriptor.MakeStatus 
    1716 
    1817from OWDataTable import ExampleTableModel 
     18 
    1919 
    2020class standard_icons(object): 
     
    2525        else: 
    2626            self.style = qwidget.style() 
    27      
     27 
    2828    @property 
    2929    def dir_open_icon(self): 
    3030        return self.style.standardIcon(QStyle.SP_DirOpenIcon) 
    31      
     31 
    3232    @property 
    3333    def reload_icon(self): 
    3434        return self.style.standardIcon(QStyle.SP_BrowserReload) 
    35      
    36      
     35 
     36 
    3737class OWCSVFileImport(OWWidget): 
    38 #    contextHandlers = {"": PathContextHandler("")} 
    39     settingsList = ["recent_files"] 
    40      
     38    settingsList = ["recent_files", "hints"] 
     39 
    4140    DELIMITERS = [("Tab", "\t"), 
    4241                  ("Comma", ","), 
     
    4544                  ("Others", None), 
    4645                  ] 
    47      
    48     def __init__(self, parent=None, signalManager=None,  
     46 
     47    def __init__(self, parent=None, signalManager=None, 
    4948                 title="CSV File Import"): 
    50          
    51         OWWidget.__init__(self, parent, signalManager, title,  
     49        OWWidget.__init__(self, parent, signalManager, title, 
    5250                          wantMainArea=False) 
    53          
     51 
    5452        self.inputs = [] 
    5553        self.outputs = [("Data", Orange.data.Table)] 
    56          
     54 
    5755        # Settings 
    5856        self.delimiter = "," 
     
    6058        self.quote = '"' 
    6159        self.missing = "" 
    62          
     60 
    6361        self.skipinitialspace = True 
    6462        self.has_header = True 
    6563        self.has_orange_header = True 
    66          
     64 
     65        # List of recent opened files. 
    6766        self.recent_files = [] 
    68          
    69         # Hints for the recent files  
     67 
     68        # Hints for the recent files 
    7069        self.hints = {} 
    71          
     70 
    7271        self.loadSettings() 
    73          
     72 
    7473        self.recent_files = filter(os.path.exists, self.recent_files) 
    75          
     74        self.hints = dict([item for item in self.hints.items() \ 
     75                           if item[0] in self.recent_files]) 
     76 
    7677        layout = QHBoxLayout() 
    7778        box = OWGUI.widgetBox(self.controlArea, "File", orientation=layout) 
    78         self.style().standardIcon(QStyle.SP_DirOpenIcon) 
     79 
    7980        icons = standard_icons(self) 
    80          
     81 
    8182        self.recent_combo = QComboBox(self, objectName="recent_combo", 
    8283                                      toolTip="Recent files.", 
    8384                                      activated=self.on_select_recent) 
    84         self.recent_combo.addItems([os.path.basename(p) for p in self.recent_files]) 
    85          
     85        self.recent_combo.addItems([os.path.basename(p) \ 
     86                                    for p in self.recent_files]) 
     87 
    8688        self.browse_button = QPushButton("...", icon=icons.dir_open_icon, 
    8789                                         toolTip="Browse filesystem", 
    8890                                         clicked=self.on_open_dialog) 
    89          
    90 #        self.reload_button = QPushButton("Reload", icon=icons.reload_icon, 
    91 #                                         clicked=self.reload_file) 
    92          
     91 
     92        self.reload_button = QPushButton("Reload", icon=icons.reload_icon, 
     93                                         toolTip="Reload the selected file", 
     94                                         clicked=self.on_reload_file) 
     95 
    9396        layout.addWidget(self.recent_combo, 2) 
    9497        layout.addWidget(self.browse_button) 
    95 #        layout.addWidget(self.reload_button) 
     98        layout.addWidget(self.reload_button) 
    9699 
    97100        ################# 
     
    103106        box = OWGUI.widgetBox(self.controlArea, "Cell Separator", 
    104107                              orientation=grid_layout) 
    105          
     108 
    106109        button_group = QButtonGroup(box) 
    107         QObject.connect(button_group,  
     110        QObject.connect(button_group, 
    108111                        SIGNAL("buttonPressed(int)"), 
    109112                        self.delimiter_changed 
    110113                        ) 
    111          
     114 
    112115        for i, (name, char) in  enumerate(self.DELIMITERS[:-1]): 
    113116            button = QRadioButton(name, box, 
    114117                                  toolTip="Use %r as cell separator" % char) 
    115              
    116118            button_group.addButton(button, i) 
    117119            grid_layout.addWidget(button, i / 3, i % 3) 
    118              
     120 
    119121        button = QRadioButton("Other", box, 
    120122                              toolTip="Use other character") 
    121          
     123 
    122124        button_group.addButton(button, i + 1) 
    123125        grid_layout.addWidget(button, i / 3 + 1, 0) 
    124126        self.delimiter_button_group = button_group 
    125              
    126         self.delimiter_edit = QLineEdit(objectName="delimiter_edit", 
    127                                         text=self.other_delimiter or self.delimiter, 
    128                                         editingFinished=self.delimiter_changed, 
    129                                         toolTip="Cell delimiter character.") 
    130          
     127 
     128        self.delimiter_edit = \ 
     129            QLineEdit(objectName="delimiter_edit", 
     130                      text=self.other_delimiter or self.delimiter, 
     131                      editingFinished=self.delimiter_changed, 
     132                      toolTip="Cell delimiter character.") 
     133 
    131134        grid_layout.addWidget(self.delimiter_edit, i / 3 + 1, 1, -1, -1) 
    132          
     135 
    133136        preset = [d[1] for d in self.DELIMITERS[:-1]] 
    134137        if self.delimiter in preset: 
     
    140143            button.setChecked(True) 
    141144            self.delimiter_edit.setEnabled(True) 
    142          
     145 
    143146        ############### 
    144147        # Other options 
     
    147150        box = OWGUI.widgetBox(self.controlArea, "Other Options", 
    148151                              orientation=form) 
    149          
     152 
    150153        self.quote_edit = QLineEdit(objectName="quote_edit", 
    151154                                    text=self.quote, 
    152155                                    editingFinished=self.quote_changed, 
    153156                                    toolTip="Text quote character.") 
    154          
     157 
    155158        form.addRow("Quote", self.quote_edit) 
    156          
    157         self.missing_edit = QLineEdit(objectName="missing_edit", 
    158                                       text=self.missing, 
    159                                       editingFinished=self.missing_changed, 
    160                                       toolTip="Missing value flags (separated by a comma)." 
    161                                       ) 
    162          
     159 
     160        self.missing_edit = \ 
     161            QLineEdit(objectName="missing_edit", 
     162                          text=self.missing, 
     163                          editingFinished=self.missing_changed, 
     164                          toolTip="Missing value flags (separated by a comma)." 
     165                          ) 
     166 
    163167        form.addRow("Missing values", self.missing_edit) 
    164          
     168 
    165169        self.skipinitialspace_check = \ 
    166                 QCheckBox(objectName="skipinitialspace_check", 
    167                           checked=self.skipinitialspace, 
    168                           text="Skip initial whitespace", 
    169                           toolTip="Skip any whitespace at the beginning of each cell.", 
    170                           toggled=self.skipinitialspace_changed 
    171                           ) 
    172                  
     170            QCheckBox(objectName="skipinitialspace_check", 
     171                  checked=self.skipinitialspace, 
     172                  text="Skip initial whitespace", 
     173                  toolTip="Skip any whitespace at the beginning of each cell.", 
     174                  clicked=self.skipinitialspace_changed 
     175                  ) 
     176 
    173177        form.addRow(self.skipinitialspace_check) 
    174                  
     178 
    175179        self.has_header_check = \ 
    176180                QCheckBox(objectName="has_header_check", 
     
    178182                          text="Header line", 
    179183                          toolTip="Use the first line as a header", 
    180                           toggled=self.has_header_changed 
     184                          clicked=self.has_header_changed 
    181185                          ) 
    182          
     186 
    183187        form.addRow(self.has_header_check) 
    184          
     188 
    185189        self.has_orange_header_check = \ 
    186190                QCheckBox(objectName="has_orange_header_check", 
    187191                          checked=self.has_orange_header, 
    188192                          text="Has orange variable type definitions", 
    189                           toolTip="Use second and third line as a orange style '.tab' format feature definitions.", 
    190                           toggled=self.has_orange_header_changed 
     193                          toolTip="Use second and third line as a orange style" 
     194                                  "'.tab' format feature definitions.", 
     195                          clicked=self.has_orange_header_changed 
    191196                          ) 
    192                  
     197 
    193198        form.addRow(self.has_orange_header_check) 
    194          
     199 
    195200        box = OWGUI.widgetBox(self.controlArea, "Preview") 
    196201        self.preview_view = QTableView() 
    197202        box.layout().addWidget(self.preview_view) 
    198          
     203 
    199204        OWGUI.button(self.controlArea, self, "Send", callback=self.send_data) 
    200          
     205 
    201206        self.selected_file = None 
    202207        self.data = None 
    203          
     208 
    204209        self.resize(450, 500) 
    205210        if self.recent_files: 
    206             QTimer.singleShot(1, lambda: self.set_selected_file(self.recent_files[0])) 
    207          
     211            QTimer.singleShot(1, 
     212                    lambda: self.set_selected_file(self.recent_files[0]) 
     213                    ) 
     214 
    208215    def on_select_recent(self, recent): 
    209216        if isinstance(recent, int): 
    210217            recent = self.recent_files[recent] 
    211          
     218 
    212219        self.set_selected_file(recent) 
    213      
    214     def on_open_dialog(self):  
     220 
     221    def on_open_dialog(self): 
    215222        last = os.path.expanduser("~/Documents") 
    216223        path = QFileDialog.getOpenFileName(self, "Open File", last) 
     
    218225        if path: 
    219226            self.set_selected_file(path) 
    220      
     227 
     228    def on_reload_file(self): 
     229        if self.recent_files: 
     230            self.set_selected_file(self.recent_files[0]) 
     231 
    221232    def delimiter_changed(self, index=-1): 
    222233        self.delimiter = self.DELIMITERS[index][1] 
     
    224235            self.other_delimiter = str(self.delimiter_edit.text()) 
    225236        self.update_preview() 
    226      
     237 
    227238    def quote_changed(self): 
    228239        if self.quote_edit.text(): 
    229240            self.quote = str(self.quote_edit.text()) 
    230241            self.update_preview() 
    231              
     242 
    232243    def missing_changed(self): 
    233244        self.missing = str(self.missing_edit.text()) 
    234245        self.update_preview() 
    235              
     246 
    236247    def has_header_changed(self): 
    237248        self.has_header = self.has_header_check.isChecked() 
    238249        self.update_preview() 
    239          
     250 
    240251    def has_orange_header_changed(self): 
    241252        self.has_orange_header = self.has_orange_header_check.isChecked() 
    242253        self.update_preview() 
    243          
     254 
    244255    def skipinitialspace_changed(self): 
    245256        self.skipinitialspace = self.skipinitialspace_check.isChecked() 
    246257        self.update_preview() 
    247              
     258 
    248259    def set_selected_file(self, filename): 
    249260        basedir, name = os.path.split(filename) 
    250          
    251261        index_to_remove = None 
    252262        if filename in self.recent_files: 
     
    255265            # Always keep 20 latest files in the list. 
    256266            index_to_remove = self.recent_combo.count() - 1 
    257          
    258267        self.recent_combo.insertItem(0, name) 
    259268        self.recent_combo.setCurrentIndex(0) 
    260269        self.recent_files.insert(0, filename) 
    261              
    262         if index_to_remove is not None:     
     270 
     271        if index_to_remove is not None: 
    263272            self.recent_combo.removeItem(index_to_remove + 1) 
    264273            self.recent_files.pop(index_to_remove + 1) 
    265             if filename in self.hints: 
    266                 del self.hints[filename] 
    267          
     274 
    268275        if filename in self.hints: 
    269276            hints = self.hints[filename] 
     
    271278            hints = sniff_csv(filename) 
    272279            self.hints[filename] = hints 
    273          
     280 
    274281        delimiter = hints["delimiter"] 
    275          
     282 
    276283        # Update the widget state (GUI) from the saved hints for the file 
    277284        preset = [d[1] for d in self.DELIMITERS[:-1]] 
     
    290297            button.setChecked(True) 
    291298            self.delimiter_edit.setEnabled(False) 
    292          
     299 
    293300        self.quote = hints["quotechar"] 
    294301        self.quote_edit.setText(self.quote) 
    295          
     302 
    296303        self.missing = hints["DK"] or "" 
    297304        self.missing_edit.setText(self.missing) 
    298          
     305 
    299306        self.has_header = hints["has_header"] 
    300307        self.has_header_check.setChecked(self.has_header) 
    301          
     308 
    302309        self.has_orange_header = hints["has_orange_header"] 
    303310        self.has_orange_header_check.setChecked(self.has_orange_header) 
    304          
     311 
    305312        self.skipinitialspace = hints["skipinitialspace"] 
    306313        self.skipinitialspace_check.setChecked(self.skipinitialspace) 
    307          
     314 
    308315        self.selected_file = filename 
    309316        self.selected_file_head = [] 
     
    311318            for i, line in zip(range(30), f): 
    312319                self.selected_file_head.append(line) 
    313          
    314         self.update_preview() 
    315          
     320 
     321        self.update_preview() 
     322 
    316323    def update_preview(self): 
    317324        self.error(0) 
     
    319326            head = StringIO("".join(self.selected_file_head)) 
    320327            hints = self.hints[self.selected_file] 
    321              
     328 
    322329            # Save hints for the selected file 
    323330            hints["quote"] = self.quote 
     
    325332            hints["has_header"] = self.has_header 
    326333            hints["has_orange_header"] = self.has_orange_header 
    327             hints["skipinitialspace"] = self.skipinitialspace  
     334            hints["skipinitialspace"] = self.skipinitialspace 
    328335            hints["DK"] = self.missing or None 
    329336            try: 
    330337                data = Orange.data.io.load_csv(head, delimiter=self.delimiter, 
    331                                                quotechar=self.quote, 
    332                                                has_header=self.has_header, 
    333                                                has_types=self.has_orange_header, 
    334                                                has_annotations=self.has_orange_header, 
    335                                                skipinitialspace=self.skipinitialspace, 
    336                                                DK=self.missing or None, 
    337                                                create_new_on=MakeStatus.OK) 
     338                                   quotechar=self.quote, 
     339                                   has_header=self.has_header, 
     340                                   has_types=self.has_orange_header, 
     341                                   has_annotations=self.has_orange_header, 
     342                                   skipinitialspace=self.skipinitialspace, 
     343                                   DK=self.missing or None, 
     344                                   create_new_on=MakeStatus.OK) 
    338345            except Exception, ex: 
    339346                self.error(0, "Cannot parse (%r)" % ex) 
    340347                data = None 
    341                  
     348 
    342349            if data is not None: 
    343350                model = ExampleTableModel(data, None, self) 
     
    345352                model = None 
    346353            self.preview_view.setModel(model) 
    347              
     354 
    348355    def send_data(self): 
    349356        self.error(0) 
    350357        if self.selected_file: 
    351             hints = self.hints[self.selected_file] 
    352358            try: 
    353359                data = Orange.data.io.load_csv(self.selected_file, 
    354                                                delimiter=self.delimiter, 
    355                                                quotechar=self.quote, 
    356                                                has_header=self.has_header, 
    357                                                has_annotations=self.has_orange_header, 
    358                                                skipinitialspace=self.skipinitialspace, 
    359                                                DK=self.missing or None, 
    360                                                create_new_on=MakeStatus.OK 
    361                                                ) 
     360                                   delimiter=self.delimiter, 
     361                                   quotechar=self.quote, 
     362                                   has_header=self.has_header, 
     363                                   has_annotations=self.has_orange_header, 
     364                                   skipinitialspace=self.skipinitialspace, 
     365                                   DK=self.missing or None, 
     366                                   create_new_on=MakeStatus.OK 
     367                                   ) 
    362368            except Exception, ex: 
    363                 self.error(0, "An error occurred while loading the file:\n\t%r" % ex) 
     369                self.error(0, "An error occurred while " 
     370                              "loading the file:\n\t%r" % ex 
     371                              ) 
    364372                data = None 
    365373            self.data = data 
    366374        self.send("Data", self.data) 
    367          
    368          
     375 
     376 
    369377def sniff_csv(file): 
    370378    snifer = csv.Sniffer() 
    371379    if isinstance(file, basestring): 
    372380        file = open(file, "rb") 
    373      
    374     sample = file.read(2 ** 20) # max 1MB sample 
     381 
     382    sample = file.read(2 ** 20)  # max 1MB sample 
    375383    dialect = snifer.sniff(sample) 
    376384    has_header = snifer.has_header(sample) 
    377      
     385 
    378386    return {"delimiter": dialect.delimiter, 
    379387            "doublequote": dialect.doublequote, 
     
    387395            "DK": None, 
    388396            } 
    389      
     397 
    390398if __name__ == "__main__": 
    391399    import sys 
     
    395403    app.exec_() 
    396404    w.saveSettings() 
    397          
    398          
    399          
    400          
Note: See TracChangeset for help on using the changeset viewer.