Ignore:
Timestamp:
03/15/12 14:48:27 (2 years ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
rebase_source:
8d80acd5f7df27caa013b7f071ad045ad9a0b7ef
Message:

Bug fixes to csv importer, added skip initial whitespace and missing values flag option.

File:
1 edited

Legend:

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

    r10529 r10533  
    1616#from OWFile import FileNameContextHandler as PathContextHandler 
    1717from OWDataTable import ExampleTableModel 
    18  
    19 DEFAULT_OPTIONS = {"delimiter":",",  
    20                    "quote":"'",  
    21                    "has_header": True, 
    22                    "has_orange_definitions": False, 
    23                    } 
    2418 
    2519Slot = pyqtSlot 
     
    4236     
    4337     
    44              
    45              
    4638class OWCSVFileImport(OWWidget): 
    4739#    contextHandlers = {"": PathContextHandler("")} 
     
    5446                  ("Others", None), 
    5547                  ] 
     48     
    5649    def __init__(self, parent=None, signalManager=None,  
    5750                 title="CSV File Import"): 
     
    6558        # Settings 
    6659        self.delimiter = "," 
     60        self.other_delimiter = None 
    6761        self.quote = '"' 
    68          
     62        self.missing = "" 
     63         
     64        self.skipinitialspace = True 
    6965        self.has_header = True 
    7066        self.has_orange_header = True 
    7167         
    7268        self.recent_files = [] 
     69         
     70        # Hints for the recent files  
    7371        self.hints = {} 
    7472         
    7573        self.loadSettings() 
    7674         
    77         self.recent_file = filter(os.path.exists, self.recent_files) 
    78          
    79         self.csv_options = dict(DEFAULT_OPTIONS) 
     75        self.recent_files = filter(os.path.exists, self.recent_files) 
    8076         
    8177        layout = QHBoxLayout() 
     
    10096#        layout.addWidget(self.reload_button) 
    10197 
    102         form_left = QFormLayout() 
    103         form_right = QFormLayout() 
    104         h_layout = QHBoxLayout() 
     98        ################# 
     99        # Cell separators 
     100        ################# 
    105101        grid_layout = QGridLayout() 
    106102        grid_layout.setVerticalSpacing(4) 
     
    112108        QObject.connect(button_group,  
    113109                        SIGNAL("buttonPressed(int)"), 
    114                         self.delimiter_changed) 
    115 #        button_group.buttonPressed.connect(self.delimiter_changed) 
     110                        self.delimiter_changed 
     111                        ) 
    116112         
    117113        for i, (name, char) in  enumerate(self.DELIMITERS[:-1]): 
     
    130126             
    131127        self.delimiter_edit = QLineEdit(objectName="delimiter_edit", 
    132                                         text=self.delimiter, 
     128                                        text=self.other_delimiter or self.delimiter, 
    133129                                        editingFinished=self.delimiter_changed, 
    134130                                        toolTip="Cell delimiter character.") 
     131         
    135132        grid_layout.addWidget(self.delimiter_edit, i / 3 + 1, 1, -1, -1) 
     133         
     134        preset = [d[1] for d in self.DELIMITERS[:-1]] 
     135        if self.delimiter in preset: 
     136            index = preset.index(self.delimiter) 
     137            b = button_group.button(index) 
     138            b.setChecked(True) 
     139            self.delimiter_edit.setEnabled(False) 
     140        else: 
     141            button.setChecked(True) 
     142            self.delimiter_edit.setEnabled(True) 
     143         
     144        ############### 
     145        # Other options 
     146        ############### 
     147        form = QFormLayout() 
     148        box = OWGUI.widgetBox(self.controlArea, "Other Options", 
     149                              orientation=form) 
    136150         
    137151        self.quote_edit = QLineEdit(objectName="quote_edit", 
     
    140154                                    toolTip="Text quote character.") 
    141155         
    142         form = QFormLayout() 
    143         box = OWGUI.widgetBox(self.controlArea, "Other Options", 
    144                               orientation=form) 
    145          
    146 #        form_left.addRow("Delimiter", self.delimiter_edit) 
    147156        form.addRow("Quote", self.quote_edit) 
    148157         
     158        self.missing_edit = QLineEdit(objectName="missing_edit", 
     159                                      text=self.missing, 
     160                                      editingFinished=self.missing_changed, 
     161                                      toolTip="Missing value flags (separated by a comma)." 
     162                                      ) 
     163         
     164        form.addRow("Missing values", self.missing_edit) 
     165         
     166        self.skipinitialspace_check = \ 
     167                QCheckBox(objectName="skipinitialspace_check", 
     168                          checked=self.skipinitialspace, 
     169                          text="Skip initial whitespace", 
     170                          toolTip="Skip any whitespace at the beginning of each cell.", 
     171                          toggled=self.skipinitialspace_changed 
     172                          ) 
     173                 
     174        form.addRow(self.skipinitialspace_check) 
     175                 
    149176        self.has_header_check = \ 
    150177                QCheckBox(objectName="has_header_check", 
     
    176203        self.data = None 
    177204         
    178         self.resize(400, 350) 
     205        self.resize(450, 500) 
     206        if self.recent_files: 
     207            QTimer.singleShot(1, lambda: self.set_selected_file(self.recent_files[0])) 
    179208         
    180209    def on_select_recent(self, recent): 
     
    191220            basedir, name = os.path.split(path) 
    192221            self.recent_combo.insertItem(0, name) 
     222            self.recent_combo.setCurrentIndex(0) 
    193223            self.recent_files.insert(0, path) 
    194224            self.set_selected_file(path) 
     
    206236            self.update_preview() 
    207237             
     238    def missing_changed(self): 
     239        self.missing = str(self.missing_edit.text()) 
     240        self.update_preview() 
     241             
    208242    def has_header_changed(self): 
    209243        self.has_header = self.has_header_check.isChecked() 
     
    212246    def has_orange_header_changed(self): 
    213247        self.has_orange_header = self.has_orange_header_check.isChecked() 
     248        self.update_preview() 
     249         
     250    def skipinitialspace_changed(self): 
     251        self.skipinitialspace = self.skipinitialspace_check.isChecked() 
    214252        self.update_preview() 
    215253             
     
    222260         
    223261        delimiter = hints["delimiter"] 
     262         
     263        # Update the widget state (GUI) from the saved hints for the file 
    224264        preset = [d[1] for d in self.DELIMITERS[:-1]] 
    225265        if delimiter not in preset: 
    226266            self.delimiter = None 
    227267            self.other_delimiter = delimiter 
     268            index = len(self.DELIMITERS) - 1 
     269            button = self.delimiter_button_group.button(index) 
     270            button.setChecked(True) 
    228271            self.delimiter_edit.setText(self.other_delimiter) 
    229272            self.delimiter_edit.setEnabled(True) 
    230273        else: 
     274            self.delimiter = delimiter 
    231275            index = preset.index(delimiter) 
    232276            button = self.delimiter_button_group.button(index) 
     
    237281        self.quote_edit.setText(self.quote) 
    238282         
     283        self.missing = hints["DK"] or "" 
     284        self.missing_edit.setText(self.missing) 
     285         
    239286        self.has_header = hints["has_header"] 
    240287        self.has_header_check.setChecked(self.has_header) 
     
    242289        self.has_orange_header = hints["has_orange_header"] 
    243290        self.has_orange_header_check.setChecked(self.has_orange_header) 
     291         
     292        self.skipinitialspace = hints["skipinitialspace"] 
     293        self.skipinitialspace_check.setChecked(self.skipinitialspace) 
    244294         
    245295        self.selected_file = filename 
     
    252302         
    253303    def update_preview(self): 
     304        self.error(0) 
    254305        if self.selected_file: 
    255306            head = StringIO("".join(self.selected_file_head)) 
    256307            hints = self.hints[self.selected_file] 
    257308             
     309            # Save hints for the selected file 
    258310            hints["quote"] = self.quote 
    259311            hints["delimiter"] = self.delimiter or self.other_delimiter 
    260312            hints["has_header"] = self.has_header 
    261             hints["has_orange_header"] = self.has_orange_header  
    262              
     313            hints["has_orange_header"] = self.has_orange_header 
     314            hints["skipinitialspace"] = self.skipinitialspace  
     315            hints["DK"] = self.missing or None 
    263316            try: 
    264317                data = Orange.data.io.load_csv(head, delimiter=self.delimiter, 
     
    267320                                               has_types=self.has_orange_header, 
    268321                                               has_annotations=self.has_orange_header, 
     322                                               skipinitialspace=self.skipinitialspace, 
     323                                               DK=self.missing or None 
    269324                                               ) 
    270325            except Exception, ex: 
    271326                self.error(0, "Cannot parse (%r)" % ex) 
    272                 self.data = None 
    273                 return 
    274             model = ExampleTableModel(data, None, self) 
     327                data = None 
     328                 
     329            if data is not None: 
     330                model = ExampleTableModel(data, None, self) 
     331            else: 
     332                model = None 
    275333            self.preview_view.setModel(model) 
     334             
     335    def send_data(self): 
     336        self.error(0) 
     337        if self.selected_file: 
     338            hints = self.hints[self.selected_file] 
     339            try: 
     340                data = Orange.data.io.load_csv(self.selected_file, 
     341                                               delimiter=self.delimiter, 
     342                                               quotechar=self.quote, 
     343                                               has_header=self.has_header, 
     344                                               has_annotations=self.has_orange_header, 
     345                                               skipinitialspace=self.skipinitialspace, 
     346                                               DK=self.missing or None 
     347                                               ) 
     348            except Exception, ex: 
     349                self.error(0, "An error occurred while loading the file:\n\t%r" % ex) 
     350                data = None 
    276351            self.data = data 
    277              
    278     def send_data(self): 
    279352        self.send("Data", self.data) 
    280353         
     
    296369            "skipinitialspace": dialect.skipinitialspace, 
    297370            "has_header": has_header, 
    298             "has_orange_header": False} 
     371            "has_orange_header": False, 
     372            "skipinitialspace": True, 
     373            "DK": None, 
     374            } 
    299375     
    300376if __name__ == "__main__": 
Note: See TracChangeset for help on using the changeset viewer.