# cerbero - a multi-platform build system for Open Source software
# Copyright (C) 2012 Andoni Morales Alastruey <ylatuya@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import os

from cerbero.build import build
from cerbero.build import source
from cerbero.utils import  N_


class MetaRecipe(type):

    def __new__(cls, name, bases, dct):
        if bases[0] != object :
            basedict = {'btype': None, 'stype': None}
            basedict['stype'] = bases[0].stype
            basedict['btype'] = bases[0].btype
            for base in ['stype', 'btype']:
                if dct.get(base):
                    basedict[base] = dct[base]
            bases = bases + tuple(basedict.values())
        return type.__new__(cls, name, bases, dct)


class Recipe(object):
    '''
    Base class for recipes.
    A Recipe describes a module and the way it's built.

    @cvar name: name of the module
    @type name: str
    @cvar version: version of the module
    @type version: str
    @cvar sources: url of the sources
    @type sources: str
    @cvar stype: type of sources
    @type stype: L{cerbero.source.SourceType}
    @cvar btype: build type
    @type btype: L{cerbero.build.BuildType}
    @cvar deps: module dependencies
    @type deps: list
    @cvar platform_deps: platform conditional depencies
    @type platform_deps: dict
    '''

    __metaclass__ = MetaRecipe

    name = None
    version = None
    package_name = None
    sources = None
    stype = source.SourceType.GIT_TARBALL
    btype = build.BuildType.AUTOTOOLS
    deps = list()
    platform_deps = {}
    force = False
    _steps = [(N_('Fetch'), 'fetch'), (N_('Extract'), 'extract'),
              (N_('Configure'), 'configure'), (N_('Compile'), 'compile'),
              (N_('Install'), 'install'),
              (N_('Post Install'), 'post_install')]
              # Not adding check as it's not automaticall done

    def __init__(self, config):
        self.config = config
        if self.package_name is None:
            self.package_name = "%s-%s" % (self.name, self.version)
        self.repo_dir = os.path.join(self.config.local_sources, self.package_name)
        self.repo_dir = os.path.abspath(self.repo_dir)
        self.build_dir = os.path.join(self.config.sources, self.package_name)
        self.build_dir = os.path.abspath(self.build_dir)
        self.stype.__init__(self)
        self.btype.__init__(self)

    def prepare(self):
        '''
        Can be overriden by subclasess to modify the recipe in function of
        the configuration, like modifying steps for a given platform
        '''
        pass

    def post_install (self):
        pass

    def list_deps(self):
        '''
        List all dependencies including conditional depencies
        '''
        deps = self.deps or []
        if self.config.target_platform in self.platform_deps:
            deps.extend(self.platform_deps[self.config.target_platform])
        return deps

    def _remove_steps(self, steps):
        self._steps = [x for x in self._steps if x[1] not in steps]

@@ -992,166 +992,718 @@
 e):%0A
-%0A    def __new__(cls, name, bases, dct):%0A        if bases%5B0%5D != object :%0A            basedict = %7B'btype': None, 'stype': None%7D%0A            basedict%5B
+    ''' This metaclass modifies the base classes of a Receipt, adding 2 new%0A    base classes based on the class attributes 'stype' and 'btype'.%0A%0A    class NewReceipt(Receipt):%0A        btype = Class1    ------%3E  class NewReceipt(Receipt, Class1, Class2)%0A        stype = Class2%0A    '''%0A%0A    def __new__(cls, name, bases, dct):%0A        clsname = '%25s.%25s' %25 (dct%5B'__module__'%5D, name)%0A        recipeclsname = '%25s.%25s' %25 (cls.__module__, 'Recipe')%0A        # only modify it for Receipt's subclasses%0A        if clsname != recipeclsname:%0A            # get the default build and source classes from Receipt%0A            # Receipt(DefaultSourceType, DefaultBaseType)%0A            basedict = %7B'btype': bases%5B0%5D.btype, 
 'stype'
-%5D =
+:
  bas
@@ -1709,24 +1709,25 @@
 ses%5B0%5D.stype
+%7D
 %0A           
@@ -1731,42 +1731,133 @@
     
-basedict%5B'btype'%5D = bases%5B0%5D.bt
+# if this class define stype or btype, override the default one%0A            # Receipt(OverridenSourceType, OverridenBaseT
 ype
+)
 %0A   
@@ -1920,21 +1920,19 @@
  if 
-dct.get(base)
+base in dct
 :%0A  
@@ -1976,16 +1976,146 @@
 t%5Bbase%5D%0A
+            # finally add this classes the Receipt bases%0A            # Receipt(BaseClass, OverridenSourceType, OverridenBaseType)%0A
         
@@ -3793,24 +3793,41 @@
 .build_dir)%0A
+        try:%0A    
         self
@@ -3848,16 +3848,20 @@
 _(self)%0A
+    
         
@@ -3885,16 +3885,163 @@
 __(self)
+%0A        except TypeError:%0A            # should only work with subclasses that really have Build and Source%0A            # in bases%0A            pass
 %0A%0A    de

Make the metaclass more generic and add some comments