<commit_before>#!/usr/bin/env python
"""A simple table classes written in pure python. It allows us to
index the data either by row index (integer) or by column (text label).
Data is stored by column

This class inherits from an OrderedDict
"""
from ordereddict import OrderedDict
#from collections import OrderedDict
from collections import Sequence,Mapping,Iterable,Hashable
#import warnings

#TO DO
# handling generators appropriately, these interfere with my checks
# using try/except rather than if/else?


class ColTable(object):
    """A simple table class that supports index and column indexing.
    Stores data by columns."""    
    def __init__(self, *args, **kwargs):
        """Takes the same input as a dict type but each value should be a
        sequence of the same length.
        """
        self.cols = OrderedDict(*args,**kwargs)
        self.validate()
    
    @property
    def headers(self):
        return self.cols.keys()
        
    def __repr__(self):
        try:
            return '<%s table: %s>' % (self.title or 'unnamed',','.join(self.headers))
        except AttributeError:
            return '<table object>'
        
    def validate(self):
        """checks that all columns have the same length"""
        if len(self.cols):
            try:
                lengths = [len(c) for c in self.cols.values()]                
            except TypeError as e:
                raise TypeError('not all columns have a len()')
            length = lengths[0]
            if not all([l == length for l in lengths]): raise AssertionError('Columns do not all have the same length')
        return True

    def __getitem__(self, key):
        if isinstance(key, int): 
            return OrderedDict((name,col[key]) for name,col in self.cols.items())
        elif isinstance(key, slice): #return another instance of class
            return ColTable((name,col[key]) for name,col in self.cols.items())
        else:
            try:
                return self.cols[key]
            except ValueError:
                raise KeyError('column does not exist')            
    
    def __setitem__(self, key, value):
        if isinstance(key, int):
            try:
                for name,col in self.cols.items():
                    col[key] = value[name]
            except ValueError as e:
                raise ValueError('row update does not include all columns')
            except TypeError as e: #not a mappable so try sequence-type code.
                #value = list(value) #handles case where value is an generator
                if len(value) != len(self.cols): raise ValueError('row update does not have enough columns')
                for col,v in zip(self.cols.values(),value):
                    col[key] = v  
        elif isinstance(key, slice): #value might be an iterable in this case
            #value = list(value) #handles case where value is an generator
            try:
                for (name,col) in self.cols.items():
                    col[key] = (row[name] for row in value)               
            except ValueError as e:
                raise ValueError('rows update does not include all columns in all rows')
            except TypeError as e:
                width = len(self.cols)
                if not all(len(row) == width for row in value): raise ValueError('(some of) rows update do not have enough columns')
                for i,(name,col) for self.cols.items():
                    col[key] = (row[i] for row in value)
        else:
            self.cols[key] = value
            self.validate()
    
    def __delitem__(self, key):
        if not (isinstance(key, int) or isinstance(key, slice)):
            try:
                del self.cols[key]
            except ValueError:
                raise KeyError('column does not exist')
        else:
            for h,col in self.cols.iteritems():
                del col[key]
                self.cols[h] = col
    
    def __iter__(self):
        """iterate over the rows rather than the columns (can always access the cols
        attribute directly)."""
            #return (dict((name,col[i]) for name,col in self.cols.items())  for i in range(len(self))
            #return (tuple(col[i] for col in self.cols.values())  for i in range(len(self))
            #namedtuple? 
            #return (list(col[i] for col in self.cols.values())  for i in range(len(self))
            return (OrderedDict((name,col[i]) for name,col in self.cols.items())  for i in range(len(self))
        
    def __len__(self):
        """number of rows in the dataset"""
        return len(self.cols.values()[0]) #assuming that collection is self-consistant
        
    def select(self,headers):
        """retrieve only selected columns from the dataset. Data is returned as another
        ColTable class.
        
        headers - iterable of columns to return, requested ordering is preserved"""
        return ColTable((key,self.col[key]) for key in headers)        
        
    def insertcol(self,index,key,value):
        """inserted a column of data before index"""
        #need to create a new OrderedDict
        headers = self.headers
        headers.insert(index, key)
        self[key] = value # append new column onto end
        newdict = OrderedDict((h,datadict[h]) for h in headers)
        self.cols = newdict #replace current cols OrderedDict with new one.
    
    def insert(self, index, row):
        """insert row before index"""
        if len(row) != len(self.cols): raise ValueError('row insert does not have enough columns')
        if isinstance(row,Mappable):
            for key,col in self.cols.iteritems():
                #Add code here to handle row types other than list
                col.insert(index,row[key])
                #self.cols[key] = col            
        else:
            for (key,col),v in zip(self.cols.iteritems(),row):
                #Add code here to handle row types other than list
                col.insert(index,v)
                #self.cols[key] = col
            
    def append(self, row):
        """append a row to the table"""
        if len(row) != len(self.cols): raise ValueError('appended row does not have enough columns')
        if isinstance(row,Mappable):
            for key,col in self.cols.iteritems():
                #Add code here to handle row types other than list
                col.append(row[key])
                #self.cols[key] = col            
        else:
            for (key,col),v in zip(self.cols.iteritems(),row):
                #Add code here to handle row types other than list
                col.append(v)
                #self.cols[key] = col
    <commit_msg>OrderedDictTable: rewrote insert and append methods to use the same try/except approach<commit_after>#!/usr/bin/env python
"""A simple table classes written in pure python. It allows us to
index the data either by row index (integer) or by column (text label).
Data is stored by column

This class inherits from an OrderedDict
"""
from ordereddict import OrderedDict
#from collections import OrderedDict
from collections import Sequence,Mapping,Iterable,Hashable
#import warnings

#TO DO
# handling generators appropriately, these interfere with my checks
# using try/except rather than if/else?


class ColTable(object):
    """A simple table class that supports index and column indexing.
    Stores data by columns."""    
    def __init__(self, *args, **kwargs):
        """Takes the same input as a dict type but each value should be a
        sequence of the same length.
        """
        self.cols = OrderedDict(*args,**kwargs)
        self.validate()
    
    @property
    def headers(self):
        return self.cols.keys()
        
    def __repr__(self):
        try:
            return '<%s table: %s>' % (self.title or 'unnamed',','.join(self.headers))
        except AttributeError:
            return '<table object>'
        
    def validate(self):
        """checks that all columns have the same length"""
        if len(self.cols):
            try:
                lengths = [len(c) for c in self.cols.values()]                
            except TypeError as e:
                raise TypeError('not all columns have a len()')
            length = lengths[0]
            if not all([l == length for l in lengths]): raise AssertionError('Columns do not all have the same length')
        return True

    def __getitem__(self, key):
        if isinstance(key, int): 
            return OrderedDict((name,col[key]) for name,col in self.cols.items())
        elif isinstance(key, slice): #return another instance of class
            return ColTable((name,col[key]) for name,col in self.cols.items())
        else:
            try:
                return self.cols[key]
            except ValueError:
                raise KeyError('column does not exist')            
    
    def __setitem__(self, key, value):
        if isinstance(key, int):
            try:
                for name,col in self.cols.items():
                    col[key] = value[name]
            except ValueError as e:
                raise ValueError('row update does not include all columns')
            except TypeError as e: #not a mappable so try sequence-type code.
                #value = list(value) #handles case where value is an generator
                if len(value) != len(self.cols): raise ValueError('row update does not have enough columns')
                for col,v in zip(self.cols.values(),value):
                    col[key] = v  
        elif isinstance(key, slice): #value might be an iterable in this case
            #value = list(value) #handles case where value is an generator
            try:
                for (name,col) in self.cols.items():
                    col[key] = (row[name] for row in value)               
            except ValueError as e:
                raise ValueError('rows update does not include all columns in all rows')
            except TypeError as e:
                width = len(self.cols)
                if not all(len(row) == width for row in value): raise ValueError('(some of) rows update do not have enough columns')
                for i,(name,col) for self.cols.items():
                    col[key] = (row[i] for row in value)
        else:
            self.cols[key] = value
            self.validate()
    
    def __delitem__(self, key):
        if not (isinstance(key, int) or isinstance(key, slice)):
            try:
                del self.cols[key]
            except ValueError:
                raise KeyError('column does not exist')
        else:
            for h,col in self.cols.iteritems():
                del col[key]
                self.cols[h] = col
    
    def __iter__(self):
        """iterate over the rows rather than the columns (can always access the cols
        attribute directly)."""
            #return (dict((name,col[i]) for name,col in self.cols.items())  for i in range(len(self))
            #return (tuple(col[i] for col in self.cols.values())  for i in range(len(self))
            #namedtuple? 
            #return (list(col[i] for col in self.cols.values())  for i in range(len(self))
            return (OrderedDict((name,col[i]) for name,col in self.cols.items())  for i in range(len(self))
        
    def __len__(self):
        """number of rows in the dataset"""
        return len(self.cols.values()[0]) #assuming that collection is self-consistant
        
    def select(self,headers):
        """retrieve only selected columns from the dataset. Data is returned as another
        ColTable class.
        
        headers - iterable of columns to return, requested ordering is preserved"""
        return ColTable((key,self.col[key]) for key in headers)        
        
    def insertcol(self,index,key,value):
        """inserted a column of data before index"""
        #need to create a new OrderedDict
        headers = self.headers
        headers.insert(index, key)
        self[key] = value # append new column onto end
        newdict = OrderedDict((h,datadict[h]) for h in headers)
        self.cols = newdict #replace current cols OrderedDict with new one.
    
    def insert(self, index, row):
        """insert row before index"""
        try:
            for key,col in self.cols.iteritems():
                #Add code here to handle row types other than list
                col.insert(index,row[key])
                #self.cols[key] = col 
        except ValueError as e:
            raise ValueError('row update does not include all columns')
        except TypeError as e: #not a mappable so try sequence-type code.
            #row = list(row) #handles case where value is an generator
            if len(row) != len(self.cols): raise ValueError('appended row does not have enough columns')
            for (key,col),v in zip(self.cols.iteritems(),row):
                #Add code here to handle row types other than list
                col.insert(index,v)
                #self.cols[key] = col
            
    def append(self, row):
        """append a row to the table"""
        try:
            for key,col in self.cols.iteritems():
                #Add code here to handle row types other than list
                col.append(row[key])
                #self.cols[key] = col 
        except ValueError as e:
            raise ValueError('row update does not include all columns')
        except TypeError as e: #not a mappable so try sequence-type code.
            #row = list(row) #handles case where value is an generator
            if len(row) != len(self.cols): raise ValueError('appended row does not have enough columns')
            for (key,col),v in zip(self.cols.iteritems(),row):
                #Add code here to handle row types other than list
                col.append(v)
                #self.cols[key] = col
    
{'fraction_non_alphanumeric': 0.09547158927026247, 'fraction_numerical': 0.00028843380444188056, 'mean_word_length': 1.9514790380932112, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2838714', 'n_tokens_mistral': 3657, 'n_tokens_neox': 3579, 'n_words': 1375}