def testFileWalk(self):
        """file walking"""
        fm = FileManager(True)

        walk = list(fm.walk("%s/css/danlann.css" % self.dir, "tmp", self.exclude))
        src, dest = walk[0]

        self.assertEqual(len(walk), 1)
        self.assertEqual(src, "%s/css/danlann.css" % self.dir)
        self.assertEqual(dest, "tmp")
    def testLibraryLookup(self):
        """library file lookup"""

        # try to find filemanager.py in src/danlann and src/danlann/test
        # directories
        assert os.path.exists("%s/danlann" % self.dir)
        assert os.path.exists("%s/danlann/test" % self.dir)
        assert os.path.exists("%s/danlann/filemanager.py" % self.dir)
        assert os.path.exists("%s/danlann/test/filemanager.py" % self.dir)

        fm = FileManager(True)
        libpath = ("%s/danlann" % self.dir, "%s/danlann/test" % self.dir)
        files = list(fm.lookup(libpath, "filemanager.py"))
        self.assertEqual(files[0], os.path.join(os.getcwd(), "%s/danlann/filemanager.py" % self.dir))
        self.assertEqual(files[1], os.path.join(os.getcwd(), "%s/danlann/test/filemanager.py" % self.dir))
    def testDirWalk(self):
        """directory walking"""
        fm = FileManager(True)

        assert os.path.exists("%s/css/.svn" % self.dir)

        for src, dest in fm.walk("css", "tmp", self.exclude):
            self.assert_(not re.search(".svn", src))

        walk1 = tuple(fm.walk("%s/css" % self.dir, "tmp", self.exclude))
        walk2 = tuple(fm.walk("%s/css/" % self.dir, "tmp", self.exclude))
        self.assertEqual(walk1, walk2)

        src, dest = list(fm.walk("%s/danlann" % self.dir, "tmp", self.exclude))[0]
        self.assert_(dest.startswith("tmp/danlann"))

        src, dest = list(fm.walk("%s/danlann/test" % self.dir, "tmp", self.exclude))[0]
        self.assert_(dest.startswith("tmp/test"))
    def testDirWalk(self):
        """directory walking"""
        fm = FileManager(True)

        assert os.path.exists('%s/css/.svn' % self.dir)

        for src, dest in fm.walk('css', 'tmp', self.exclude):
            self.assert_(not re.search('.svn', src))

        walk1 = tuple(fm.walk('%s/css' % self.dir, 'tmp', self.exclude))
        walk2 = tuple(fm.walk('%s/css/' % self.dir, 'tmp', self.exclude))
        self.assertEqual(walk1, walk2)

        src, dest = list(fm.walk('%s/danlann' % self.dir, 'tmp', self.exclude))[0]
        self.assert_(dest.startswith('tmp/danlann'))

        src, dest = list(fm.walk('%s/danlann/test' % self.dir, 'tmp', self.exclude))[0]
        self.assert_(dest.startswith('tmp/test'))
 def testSingleLookup(self):
     """single file lookup"""
     fm = FileManager(True)
     fn = list(fm.lookup(["src"], "danlann"))[0]
     self.assertEqual(fn, os.path.join(os.getcwd(), "src", "danlann"))
Example #6
0
class Danlann(object):
    """
    Danlann processor reads configuration and creates all necessary objects
    required for gallery generation.

    Generating gallery is divided to specific tasks
        - read configuration
        - initialize and configure all objects
            - danlann processor
            - generator
            - file manager
            - gallery
          after this stage all objects are configured
        - parse album files; data are stored in gallery data instance
        - copy files using file manager
        - generate gallery with generator object
        - reformat and validate output files if requested

    @ivar validate:  validate generated files
    @ivar libpath:   list of gallery library paths
    @ivar outdir:    output dir, all gallery files go to output directory
    @ivar albums:    list of input album files
    @ivar files:     list of additional gallery files, which should be
                     copied to output directory 
    @ivar exclude:   definition of excluded additional files (regular
                     expression)
                     
    @ivar fm:        file manager
    @ivar gallery:   gallery data
    @ivar generator: gallery generator
    """
    def __init__(self):
        self.validate = False
        self.libpath  = [danlann.config.libpath]
        self.outdir   = None
        self.albums   = []
        self.files    = ['css', 'js']
        self.exclude  = '.svn|CVS|~$|\.swp$'

        self.fm        = None
        self.gallery   = None
        self.generator = None


    def setConvertArgs(self, conf, photo_type):
        section = 'photo:%s' % photo_type
        for option in ('size', 'quality', 'unsharp', 'params'):
            if conf.has_option(section, option):
                value = conf.get(section, option) 
                self.generator.setConvertArg(photo_type, option, value)


    def readConf(self, fn):
        """
        Read configuration file.

        @param fn: configuration file name

        @return configuration object

        @see ConfigParse
        """
        conf = ConfigParser()
        if not conf.read(fn):
            raise ConfigurationError('config file %s does not exist' % fn)
        return conf


    def initialize(self, conf, validate = None):
        """
        Initialize and configure all required instances like
            - generator
            - file manager
            - gallery

        After this stage all objects should configured including the
        processor. Therefore processor configuration is set in
        initialization method, too.

        @param conf:     configuration object
        @param validate: override validation configuration option
        """
        #
        # configure processor
        #
        if conf.has_option('danlann', 'outdir'):
            self.outdir = conf.get('danlann', 'outdir')
        else:
            raise ConfigurationError('no output directory configuration')

        if conf.has_option('danlann', 'libpath'):
            libpath = conf.get('danlann', 'libpath')

            # resolve $libpath variable
            libpath = libpath.replace('$libpath', danlann.config.libpath)

            self.libpath = libpath.split(':')

        if validate is None and conf.has_option('danlann', 'validate'):
            self.validate = conf.getboolean('danlann', 'validate')
        else:
            self.validate = validate 

        if conf.has_option('danlann', 'albums'):
            self.albums = conf.get('danlann', 'albums').split()
        else:
            raise ConfigurationError('no input album files configuration')

        if conf.has_option('danlann', 'files'):
            files = conf.get('danlann', 'files')

            # resolve $files variable
            files = files.replace('$files', ' '.join(self.files))

            self.files = files.split()

        if conf.has_option('danlann', 'exclude'):
            self.exclude = conf.get('danlann', 'exclude')

        #
        # create gallery data instance
        #
        if conf.has_option('danlann', 'title'):
            title = conf.get('danlann', 'title')
        else:
            raise ConfigurationError('no gallery title configuration')

        if conf.has_option('danlann', 'description'):
            description = conf.get('danlann', 'description')
        else:
            description = ''

        self.gallery = Gallery(title, description)

        #
        # create file manager
        #
        gm = True
        if conf.has_option('danlann', 'graphicsmagick'):
            gm = conf.getboolean('danlann', 'graphicsmagick')
        self.fm = FileManager(gm)

        #
        # create gallery generator
        #
        if conf.has_option('danlann', 'indir'):
            indir = conf.get('danlann', 'indir').split(':')
        else:
            raise ConfigurationError('no input directory configured')

        exif_headers = ['Image timestamp', 'Exposure time',
            'Aperture', 'Exposure bias', 'Flash', 'Flash bias',
            'Focal length', 'ISO speed', 'Exposure mode', 'Metering mode',
            'White balance']

        if conf.has_option('danlann', 'exif'):
            headers = conf.get('danlann', 'exif').split(',')
            exif_headers = [exif.strip() for exif in headers]

        self.generator              = DanlannGenerator(self.gallery, self.fm)
        self.generator.indir        = indir
        self.generator.outdir       = self.outdir
        self.generator.exif_headers = exif_headers

        self.setConvertArgs(conf, 'thumb')
        self.setConvertArgs(conf, 'image')

        #
        # create template object
        #
        override = None
        name = 'basic'

        # get template name
        if conf.has_option('template', 'name'):
            name = conf.get('template', 'name')

        # get template override
        if conf.has_option('template', 'override'):
            override = conf.get('template', 'override')

        tmpl = self.generator.tmpl = Template(name, self.gallery, override)

        if conf.has_option('template', 'copyright'):
            tmpl.copyright = conf.get('template', 'copyright')

        if conf.has_option('template', 'css'):
            css = conf.get('template', 'css')
            tmpl.css.extend(css.split())

        if conf.has_option('template', 'js'):
            js = conf.get('template', 'js')
            tmpl.js.extend(js.split())

        #
        # check exiv2/GraphicsMagick/ImageMagick existence
        #
        if gm:
            self.checkCommand('gm', 'GraphicsMagick (gm command)')
        else:
            self.checkCommand('convert', 'ImageMagick (convert command)')
        self.checkCommand('exiv2', 'Exiv2 (exiv2 command)')



    def copy(self):
        """
        Copy additional gallery files to gallery output directory.
        """
        assert self.outdir

        # lookup for all additional files to be copied
        files = (self.fm.lookup(self.libpath, fn) for fn in self.files)

        # copy found files
        for fn in itertools.chain(*files):
            self.fm.copy(fn, self.outdir, self.exclude)


    def parse(self):
        """
        Parse gallery data.
        """
        interpreter = parser.interpreter(self.gallery)

        # read album files
        for fn in self.albums:
            log.debug('parsing album file %s' % fn)
            f = open(fn)
            parser.load(f, interpreter)
            f.close()

        # check gallery data instance
        parser.check(interpreter, self.gallery)


    def generateGallery(self):
        """
        Generate gallery using gallery generator.
        """
        self.generator.generate()


    def postprocess(self):
        """
        Reformat and validate output files if requested.
        """
        def html_files():
            """
            Get all HTML files.
            """
            for dir, subdirs, files in os.walk(self.outdir):
                for fn in files:
                    if fn.endswith('.xhtml'):
                        yield os.path.join(dir, fn)


        for fn in html_files():
            self.fm.formatXML(fn)

            if self.validate:
                log.info('validating file: %s' % fn)
                if not self.fm.validate(fn):
                    log.error('validating failed: %s' % fn)


    def checkCommand(self, cmd, name):
        """
        Check if given command exist. If it does not exist then
        @C{ConfigurationError} exception is raised.

        @param cmd:  command to check, i.e. convert, gm
        @param name: software identyfing the command, i.e. ImageMagick,
                     GraphicsMagick
        """
        try:
            self.fm.checkCommand(cmd)
        except OSError, ex:
            raise ConfigurationError('%s is not installed, error: %s' \
                    % (name, ex.strerror))
Example #7
0
    def initialize(self, conf, validate = None):
        """
        Initialize and configure all required instances like
            - generator
            - file manager
            - gallery

        After this stage all objects should configured including the
        processor. Therefore processor configuration is set in
        initialization method, too.

        @param conf:     configuration object
        @param validate: override validation configuration option
        """
        #
        # configure processor
        #
        if conf.has_option('danlann', 'outdir'):
            self.outdir = conf.get('danlann', 'outdir')
        else:
            raise ConfigurationError('no output directory configuration')

        if conf.has_option('danlann', 'libpath'):
            libpath = conf.get('danlann', 'libpath')

            # resolve $libpath variable
            libpath = libpath.replace('$libpath', danlann.config.libpath)

            self.libpath = libpath.split(':')

        if validate is None and conf.has_option('danlann', 'validate'):
            self.validate = conf.getboolean('danlann', 'validate')
        else:
            self.validate = validate 

        if conf.has_option('danlann', 'albums'):
            self.albums = conf.get('danlann', 'albums').split()
        else:
            raise ConfigurationError('no input album files configuration')

        if conf.has_option('danlann', 'files'):
            files = conf.get('danlann', 'files')

            # resolve $files variable
            files = files.replace('$files', ' '.join(self.files))

            self.files = files.split()

        if conf.has_option('danlann', 'exclude'):
            self.exclude = conf.get('danlann', 'exclude')

        #
        # create gallery data instance
        #
        if conf.has_option('danlann', 'title'):
            title = conf.get('danlann', 'title')
        else:
            raise ConfigurationError('no gallery title configuration')

        if conf.has_option('danlann', 'description'):
            description = conf.get('danlann', 'description')
        else:
            description = ''

        self.gallery = Gallery(title, description)

        #
        # create file manager
        #
        gm = True
        if conf.has_option('danlann', 'graphicsmagick'):
            gm = conf.getboolean('danlann', 'graphicsmagick')
        self.fm = FileManager(gm)

        #
        # create gallery generator
        #
        if conf.has_option('danlann', 'indir'):
            indir = conf.get('danlann', 'indir').split(':')
        else:
            raise ConfigurationError('no input directory configured')

        exif_headers = ['Image timestamp', 'Exposure time',
            'Aperture', 'Exposure bias', 'Flash', 'Flash bias',
            'Focal length', 'ISO speed', 'Exposure mode', 'Metering mode',
            'White balance']

        if conf.has_option('danlann', 'exif'):
            headers = conf.get('danlann', 'exif').split(',')
            exif_headers = [exif.strip() for exif in headers]

        self.generator              = DanlannGenerator(self.gallery, self.fm)
        self.generator.indir        = indir
        self.generator.outdir       = self.outdir
        self.generator.exif_headers = exif_headers

        self.setConvertArgs(conf, 'thumb')
        self.setConvertArgs(conf, 'image')

        #
        # create template object
        #
        override = None
        name = 'basic'

        # get template name
        if conf.has_option('template', 'name'):
            name = conf.get('template', 'name')

        # get template override
        if conf.has_option('template', 'override'):
            override = conf.get('template', 'override')

        tmpl = self.generator.tmpl = Template(name, self.gallery, override)

        if conf.has_option('template', 'copyright'):
            tmpl.copyright = conf.get('template', 'copyright')

        if conf.has_option('template', 'css'):
            css = conf.get('template', 'css')
            tmpl.css.extend(css.split())

        if conf.has_option('template', 'js'):
            js = conf.get('template', 'js')
            tmpl.js.extend(js.split())

        #
        # check exiv2/GraphicsMagick/ImageMagick existence
        #
        if gm:
            self.checkCommand('gm', 'GraphicsMagick (gm command)')
        else:
            self.checkCommand('convert', 'ImageMagick (convert command)')
        self.checkCommand('exiv2', 'Exiv2 (exiv2 command)')
 def testSingleLookup(self):
     """single file lookup"""
     fm = FileManager(True)
     fn = list(fm.lookup(['src'], 'danlann'))[0]
     self.assertEqual(fn, os.path.join(os.getcwd(), 'src', 'danlann'))