""" Faster Metadata implementation

Based on the observation that constructing Metadata is very common, while
changing it is less so.
"""

from collections import Sequence

class Metadata(Sequence):

    def __init__(self, data, fields=None, checktypes=False):
        if fields is None:
            if isinstance(data, Metadata):      # Data is a Metadata instance
                self._data = data._data
                self._fields = data._fields
            elif hasattr(data, "keys"):         # Data is dict-like
                self._fields = tuple(data.keys())
                fst = data[self._fields[0]]
                if hasattr(fst, "__iter__") and not isinstance(fst, str):   # Vector entries
                    zipvalues = zip(*(data[f] for f in self._fields))
                    self._data = [tuple(item) for item in zipvalues]
                else:                           # Scalar entries
                    self._data = [(data[f],) for f in self._fields]
            else:                               # Data is list or scalar
                self._fields = ("value",)
                if hasattr(data, "__iter__") and not isinstance(data, str):
                    self._data = [(d,) for d in data]
                else:
                    self._data = [(data,)]
        else:
            if hasattr(data[0], "__len__") and not isinstance(data[0], str):
                if len(data[0]) != len(fields):
                    raise ValueError("Length of data entries and fields don't match")
            self._fields = tuple(fields)
            self._data = data

        if checktypes:
            self._validatetypes()
        return

    def _validatetypes(self):
        for i,t in enumerate(self.types):
            if not all(isinstance(t, d[i]) for d in self._data):
                raise TypeError("data contains item ({0}) not of type {1}".format(self._fields[i], t))
        return

    def __eq__(self, other):
        return (self._data == other._data) and (self._fields == other._fields)

    def __neq__(self, other):
        return self != other

    def __getitem__(self, i):
        return self._data[i]

    def __setitem__(self, i, val):
        self._data[i] = val
        return

    def __delitem__(self, i):
        del self._data[i]

    def __len__(self, i):
        return len(self._data)

    @property
    def data(self):
        return self._data

    @property
    def fields(self):
        return self._fields

    @property
    def types(self):
        return tuple(type(a) for a in self._data[0])

    def get(self, i):
        d = self._data[i]
        if isinstance(i, slice):
            r = {}
            for j in range(len(self._fields)):
                r[self._fields[j]] = [d_[j] for d_ in d]
            return r
        else:
            return dict((self._fields[j], d[j]) for j in range(len(self._fields)))

    def getfield(self, name):
        if name in self._fields:
            i = self._fields.index(name)
            return [d[i] for d in self._data]
        else:
            raise KeyError("'{0}' not a field name".format(name))


@@ -1,14 +1,7 @@
 %22%22%22
- Faster
  Met
@@ -10,122 +10,31 @@
 ata 
-implementation%0A%0ABased on the observation that constructing Metadata is very common, while%0Achanging it is less so.%0A
+tables for vector data 
 %22%22%22%0A
@@ -168,144 +168,719 @@
     
-if fields is None:%0A            if isinstance(data, Metadata):      # Data is a Metadata instance%0A                self._data = data._data
+%22%22%22 Create a collection of metadata from *data*.%0A%0A        *data* may be:%0A        %0A            - a list with uniform type%0A            - a dictionary with equally-sized fields of uniform type.%0A            - a scalar%0A            - another Metadata instance%0A%0A        The *kwarg* fields is used for fast Metadata object creation, and%0A        requires *data* to be provided as a list of equal-sized tuples.%0A%0A        If *checktypes* is True (default False), the values in *data* will be%0A        tested to ensure they are of constant type. In the usual case, this%0A        type-checking is foregone for speed.%0A        %22%22%22%0A        if fields is None:%0A            if hasattr(data, %22_fields%22):        # Data is Metadata-like
 %0A   
@@ -920,16 +920,56 @@
 _fields%0A
+                self._data = data._data%0A
         
@@ -1252,17 +1252,17 @@
  = zip(*
-(
+%5B
 data%5Bf%5D 
@@ -1282,17 +1282,17 @@
 ._fields
-)
+%5D
 )%0A      
@@ -2415,32 +2415,109 @@
         return%0A%0A
+    def __repr__(self):%0A        return %22D%5B%22 + %22, %22.join(self._fields) + %22%5D%22%0A%0A
     def __eq__(s
@@ -3152,32 +3152,87 @@
 f get(self, i):%0A
+        %22%22%22 Return a dictionary for a single entry %22%22%22%0A
         d = self
@@ -3539,20 +3539,21 @@
 d(self, 
-name
+field
 ):%0A     
@@ -3559,15 +3559,77 @@
     
-if name
+%22%22%22 Return list of data corresponding to *field* %22%22%22%0A        if field
  in 
@@ -3677,20 +3677,21 @@
 s.index(
-name
+field
 )%0A      
@@ -3790,20 +3790,21 @@
 a field 
-name
+field
 %22.format
@@ -3808,12 +3808,13 @@
 mat(
-name
+field
 ))%0A%0A

add repr method and documentation