"""Provide the class Index which represents an index of photos.
"""

import os
import os.path
import fnmatch
from collections import MutableSequence
import yaml
from photo.idxitem import IdxItem


class Index(MutableSequence):

    defIdxFilename = ".index.yaml"

    def __init__(self, idxfile=None, imgdir=None, hashalg=['md5']):
        super(Index, self).__init__()
        self.directory = None
        self.idxfilename = None
        self.items = []
        if idxfile:
            self.read(idxfile)
        if imgdir:
            self.readdir(imgdir, hashalg)

    def __len__(self):
        return len(self.items)

    def __getitem__(self, index):
        return self.items.__getitem__(index)

    def __setitem__(self, index, value):
        self.items.__setitem__(index, value)

    def __delitem__(self, index):
        self.items.__delitem__(index)

    def insert(self, index, value):
        self.items.insert(index, value)

    def _idxfilename(self, idxfile):
        """Determine the index file name for reading and writing.
        """
        if idxfile is not None:
            idxfile = os.path.abspath(idxfile)
            if os.path.isdir(idxfile):
                idxfile = os.path.join(idxfile, self.defIdxFilename)
            return idxfile
        elif self.idxfilename is not None:
            return self.idxfilename
        else:
            d = self.directory if self.directory is not None else os.getcwd()
            return os.path.abspath(os.path.join(d, self.defIdxFilename))

    def readdir(self, imgdir, hashalg=['md5']):
        """Add all image files in a directory to the index.
        """
        imgdir = os.path.abspath(imgdir)
        if not self.directory:
            self.directory = imgdir
        known = { i.filename for i in self.items }
        for f in sorted(os.listdir(imgdir)):
            absfile = os.path.join(imgdir, f)
            f = os.path.relpath(absfile, self.directory)
            if (os.path.isfile(absfile) and fnmatch.fnmatch(f, '*.jpg') and
                f not in known):
                self.items.append(IdxItem(filename=f, basedir=self.directory, 
                                          hashalg=hashalg))

    def read(self, idxfile=None):
        """Read the index from a file.
        """
        self.idxfilename = self._idxfilename(idxfile)
        self.directory = os.path.dirname(self.idxfilename)
        with open(self.idxfilename, 'rt') as f:
            self.items = [IdxItem(data=i) for i in yaml.load(f)]

    def write(self, idxfile=None):
        """Write the index to a file.
        """
        with open(self._idxfilename(idxfile), 'wt') as f:
            items = [i.as_dict() for i in self.items]
            yaml.dump(items, f, default_flow_style=False)

@@ -194,377 +194,1146 @@
 m%0A%0A%0A
-class Index(MutableSequence):%0A%0A    defIdxFilename = %22.index.yaml%22%0A%0A    def __init__(self, idxfile=None, imgdir=None, hashalg=%5B'md5'%5D):%0A        super(Index, self).__init__()%0A        self.directory = None%0A        self.idxfilename = None%0A        self.items = %5B%5D%0A        if idxfile:%0A            self.read(idxfile)%0A        if imgdir:%0A            self.readdir(imgdir, hashalg
+def _readdir(imgdir, basedir, hashalg, known=set()):%0A    for f in sorted(os.listdir(imgdir)):%0A        absfile = os.path.join(imgdir, f)%0A        f = os.path.relpath(absfile, basedir)%0A        if (os.path.isfile(absfile) and fnmatch.fnmatch(f, '*.jpg')%0A            and f not in known):%0A            yield IdxItem(filename=f, basedir=basedir, hashalg=hashalg)%0A%0A%0Aclass Index(MutableSequence):%0A%0A    defIdxFilename = %22.index.yaml%22%0A%0A    def __init__(self, idxfile=None, imgdir=None, hashalg=%5B'md5'%5D):%0A        super(Index, self).__init__()%0A        self.directory = None%0A        self.idxfilename = None%0A        self.items = %5B%5D%0A        if idxfile:%0A            self.read(idxfile)%0A        if imgdir:%0A            imgdir = os.path.abspath(imgdir)%0A            if not self.directory:%0A                self.directory = imgdir%0A            if idxfile:%0A                known = %7B i.filename for i in self.items %7D%0A                newitems = _readdir(imgdir, self.directory, hashalg, known)%0A                self.items.extend(newitems)%0A            else:%0A                newitems = _readdir(imgdir, self.directory, hashalg)%0A                self.items = list(newitems
 )%0A%0A 
@@ -2281,684 +2281,8 @@
 ))%0A%0A
-    def readdir(self, imgdir, hashalg=%5B'md5'%5D):%0A        %22%22%22Add all image files in a directory to the index.%0A        %22%22%22%0A        imgdir = os.path.abspath(imgdir)%0A        if not self.directory:%0A            self.directory = imgdir%0A        known = %7B i.filename for i in self.items %7D%0A        for f in sorted(os.listdir(imgdir)):%0A            absfile = os.path.join(imgdir, f)%0A            f = os.path.relpath(absfile, self.directory)%0A            if (os.path.isfile(absfile) and fnmatch.fnmatch(f, '*.jpg') and%0A                f not in known):%0A                self.items.append(IdxItem(filename=f, basedir=self.directory, %0A                                          hashalg=hashalg))%0A%0A
     

Remove method readdir() from class Index. Turn it into an internal generator function that yields the new IdxItems individually.