Beispiel #1
0
 def __init__(self, id):
     self.id         = id   # int representing bit mask for each using part turned on
     self.file       = ""   # potential file (base-)name that makes up the package, if desired
     self.classes    = []   # list of classes in this package
     #self.part_count       # property
     #self.parts      = []   # list of parts using this package  -- currently not used
     self.data       = NameSpace() # an extensible container
     self.data.resources    = {}   # {resourceId: resourceInfo}
     self.data.locales      = {}   # {"en" : {"cldr_am" : "AM"}}
     self.data.translations = {}   # {"en" : {"Hello"   : "Hallo"}}
     self.packageDeps= set(()) # set packages this package depends on
     self.compiled   = ""   # potential compiled string of the package classes
     self._hash      = ""   # property
Beispiel #2
0
    def __init__(self, id):
        global console
        self.id = id  # int representing initial bit mask for each using part turned on
        self.part_mask = id  # will be modified during mergers
        self.file = ""  # potential file (base-)name that makes up the package, if desired
        self.files = [
        ]  # list of compiled/source files making up this package; TODO: supersedes self.file
        self.classes = [
        ]  # list of classes in this package, [generator.code.Class]
        #self.part_count       # property
        #self.parts      = []   # list of parts using this package  -- currently not used
        self.data = NameSpace()  # an extensible container
        self.data.resources = {}  # {resourceId: resourceInfo}
        self.data.locales = {}  # {"en" : {"cldr_am" : "AM"}}
        self.data.translations = {}  # {"en" : {"Hello"   : "Hallo"}}
        self.packageDeps = set(
        )  # set(Package()) this package (load-)depends on
        self.compiled = []  # potential compiled strings of self.files[]
        self._hash = ""  # property
        self.has_source = False  # whether this package includes classes from their source file

        console = Context.console
Beispiel #3
0
    def _integrateExternalConfig(self,
                                 extConfig,
                                 namespace,
                                 impJobsList=None,
                                 blockJobsList=None):

        # Some helper functions

        ##
        # Construct new job name for the imported job
        def createNewJobName(extJobEntry):
            if (importJobsList
                    and extJobEntry in importJobsList and isinstance(
                        importJobsList[extJobEntry], types.DictType)):
                newjobname = namepfx + importJobsList[extJobEntry]['as']
            else:
                newjobname = namepfx + extJobEntry  # create a job name
            return newjobname

        ##
        # In case of a name collision, do some householding and return an
        # alternate job name.
        def clashPrepare(jobname):
            # import external job under different name
            jobs_ignored_shadowing = self.get("config-warnings/job-shadowing",
                                              [])
            if jobname not in jobs_ignored_shadowing:
                console.warn("! Shadowing job \"%s\" with local one" % jobname)
            # construct a name prefix
            extConfigName = extConfig._fname or self.SHADOW_PREFIX
            extConfigName = os.path.splitext(
                os.path.basename(extConfigName))[0]
            # TODO: this might not be unique enough! (user could use extConfigName in 'as' param for other include)
            newjobname = extConfigName + self.COMPOSED_NAME_SEP + jobname
            return newjobname

        def clashProcess(clashCase):
            # check whether the local job is protected
            jobMap = self.getJobsMap()
            if ((Key.OVERRIDE_KEY not in jobMap)
                    or (clashCase.name not in jobMap[Key.OVERRIDE_KEY])):
                # put shaddowed job in the local 'extend'
                if not newJob:
                    raise Error, "unsuitable new job"
                localjob = self.getJob(clashCase.name)
                extList = localjob.getFeature('extend', [])
                extList.append(newJob)
                localjob.setFeature('extend', extList)
                # add to config's shadowed list
                self._shadowedJobs[newJob] = localjob
            return

        ##
        # Fix job references, but only for the jobs from the just imported config
        def patchJobReferences(job, key, renamedJobs):
            newlist = []
            oldlist = job.getFeature(key)
            for jobentry in oldlist:
                # it's a string reference
                if isinstance(jobentry, types.StringTypes):
                    if Key.hasMacro(jobentry) and renamedJobs:
                        console.warn("Potential pitfall: Cannot rename job reference containing macros (%s#%s[\"%s\"]:%s)" \
                                        % (extConfig._fname, extJob.name, key, oldlist))
                    if jobentry in renamedJobs:
                        newlist.append(renamedJobs[jobentry])
                    else:
                        newlist.append(jobentry)
                # it's a Job() object
                else:
                    newlist.append(jobentry)
            job.setFeature(key, newlist)

        # -- Main --------------------------------------------------------------

        if namespace:
            namepfx = namespace + self.COMPOSED_NAME_SEP  # job names will be namespace'd
        else:
            namepfx = ""  # job names will not be namespace'd

        renamedJobs = {
        }  # map for job renamings - done after all jobs have been imported
        clashCase = NameSpace()  # to record a single clashing job name

        # Construct a map of import symbols (better lookup, esp. when aliased)
        importJobsList = {}
        if impJobsList:
            for e in impJobsList:
                if isinstance(e, types.StringTypes):
                    importJobsList[e] = None
                elif isinstance(e,
                                types.DictType):  # {name: <name>, as: <alias>}
                    importJobsList[e['name']] = {'as': e['as']}
                else:
                    raise TypeError, "Illegal import entry: %s (Config: %s)" % (
                        str(e), self._fname)

        # Merge global "let" -- currently disabled, see Bug#4126
        #extLet = extConfig.get(Key.LET_KEY, False)
        #if extLet:
        #    tmp = extLet.copy()
        #    tmp.update(self.get(Key.LET_KEY, {}))  # this should probably be deepMerge
        #    self.set(Key.LET_KEY, tmp)
        #    self.expandTopLevelKeys()  # we're making macro expansion in selected top-level keys eager

        # Go through the list of jobs to import
        newList = []
        extJobsList = extConfig.getExportedJobsList()
        for extJobEntry in extJobsList:
            # Checks and preparations
            if importJobsList and extJobEntry not in importJobsList:
                continue
            if blockJobsList and extJobEntry in blockJobsList:
                continue
            newjobname = createNewJobName(extJobEntry)

            # Check for name clashes
            if self.hasJob(newjobname):
                clashCase.name_clashed = True
                clashCase.name = newjobname
                newjobname = clashPrepare(newjobname)
            else:
                clashCase.name_clashed = False  # reset

            # Now process the external job
            #   take essentially the external job into the local joblist
            extJob = extConfig.getJob(extJobEntry)  # fetch this job
            if not extJob:
                raise RuntimeError, "No such job: \"%s\" while including config: \"%s\")" % (
                    extJobEntry, extConfig._fname)
            newJob = Job(
                newjobname, {}, self._console, self
            )  # fake as local job, for _includeGlobalLet to run locally
            #newJob.includeGlobalLet()  # have to draw in local let before all the external let's are processed
            newJob.includeGlobalDefaults(
            )  # have to draw in local let before all the external let's are processed
            newJob.mergeJob(extJob)  # now merge in the external guy
            newJob.setConfig(
                extJob.getConfig())  # retain link to original config
            if (newjobname !=
                    extJobEntry  # adapt modified names; otherwise, delay name resolution until resolveExtendsAndRun()
                    and not clashCase.name_clashed
                ):  # keep job references if there is shadowing
                renamedJobs[
                    extJobEntry] = newjobname  # keep string reference for later binding
            self.addJob(newjobname, newJob)  # and add it
            newList.append(
                newJob)  # memorize jobs added from extConfig for later

            # Now process a possible name clash
            if clashCase.name_clashed:
                clashProcess(clashCase)

        # Fix job references, but only for the jobs from the just imported config
        # go through the list of just added jobs again
        for job in newList:  # there is no easy way to get newList from other data
            # patch job references in 'run', 'extend', ... keys
            for key in Key.KEYS_WITH_JOB_REFS:
                if job.hasFeature(key):
                    patchJobReferences(job, key, renamedJobs)

        return
Beispiel #4
0
    def _integrateExternalConfig(self, extConfig, namespace, impJobsList=None, blockJobsList=None):
        '''jobs of external config are spliced into current job list'''
        if namespace:
            namepfx = namespace + self.COMPOSED_NAME_SEP # job names will be namespace'd
        else:
            namepfx = ""         # job names will not be namespace'd

        renamedJobs = {}         # map for job renamings - done after all jobs have been imported
        l           = NameSpace()  # for out-params of nested functions

        # Construct a map of import symbols (better lookup, esp. when aliased)
        importJobsList = {}
        if impJobsList:
            for e in impJobsList:
                if isinstance(e, types.StringTypes):
                    importJobsList[e]=None
                elif isinstance(e, types.DictType):  # {name: <name>, as: <alias>}
                    importJobsList[e['name']] = {'as': e['as']}
                else:
                    raise TypeError, "Illegal import entry: %s (Config: %s)" % (str(e), self._fname)

        # Some helper functions
        def createNewJobName(extJobEntry):
            # Construct new job name for the imported job
            if (importJobsList and extJobEntry in importJobsList 
                and isinstance(importJobsList[extJobEntry], types.DictType)):
                newjobname = namepfx + importJobsList[extJobEntry]['as']
            else:
                newjobname = namepfx + extJobEntry  # create a job name
            return newjobname

        def clashPrepare(newjobname):
            '''do some householding and return a new job name'''
            l.hasClash = True
            l.clashname = newjobname
            # import external job under different name
            console.warn("! Shadowing job \"%s\" with local one" % newjobname)
            # construct a name prefix
            extConfigName = extConfig._fname or self.SHADOW_PREFIX
            extConfigName = os.path.splitext(os.path.basename(extConfigName))[0]
            # TODO: this might not be unique enough! (user could use extConfigName in 'as' param for other include)
            newjobname = extConfigName + self.COMPOSED_NAME_SEP + newjobname
            return newjobname

        def clashProcess():
            # check whether the local job is protected
            jobMap = self.getJobsMap()
            if ((Lang.OVERRIDE_KEY not in jobMap) or
                (l.clashname not in jobMap[Lang.OVERRIDE_KEY])):
                # put shaddowed job in the local 'extend'
                if not newJob:
                    raise Error, "unsuitable new job"
                localjob = self.getJob(l.clashname)
                extList = localjob.getFeature('extend', [])
                extList.append(newJob)
                localjob.setFeature('extend', extList)
                # add to config's shadowed list
                self._shadowedJobs[newJob] = localjob


        # Go through the list of jobs to import
        newList     = []
        extJobsList = extConfig.getExportedJobsList()
        for extJobEntry in extJobsList:
            # Checks and preparations
            if importJobsList and extJobEntry not in importJobsList:
                continue
            if blockJobsList and extJobEntry in blockJobsList:
                continue
            newjobname = createNewJobName(extJobEntry)
            
            # Check for name clashes
            l.hasClash   = False
            if self.hasJob(newjobname):
                newjobname = clashPrepare(newjobname)

            # Now process the external job
            #   take essentially the external job into the local joblist
            extJob = extConfig.getJob(extJobEntry)  # fetch this job
            if not extJob:
                raise RuntimeError, "No such job: \"%s\" while including config: \"%s\")" % (extJobEntry, extConfig._fname)
            newJob = Job(newjobname, {}, self._console, self) # fake as local job, for _includeGlobalLet to run locally
            newJob.includeGlobalLet()  # have to draw in local let before all the external let's are processed
            newJob.mergeJob(extJob)    # now merge in the external guy
            newJob.setConfig(extJob.getConfig()) # retain link to original config
            if (newjobname != extJobEntry  # adapt modified names; otherwise, delay name resolution until resolveExtendsAndRun()
                and not l.hasClash):       # keep job references if there is shadowing
                renamedJobs[extJobEntry] = newjobname  # keep string reference for later binding
            self.addJob(newjobname, newJob)         # and add it
            newList.append(newJob)         # memorize jobs added from extConfig for later

            # Now process a possible name clash
            if l.hasClash:
                clashProcess()
        

        # Fix job references, but only for the jobs from the just imported config
        #   helper function
        def patchFeature(job, key, renamedJobs):
            newlist = []
            oldlist = job.getFeature(key)
            for jobentry in oldlist:
                if (isinstance(jobentry, types.StringTypes)
                    and jobentry in renamedJobs):
                    newlist.append(renamedJobs[jobentry])
                else:
                    newlist.append(jobentry)
            job.setFeature(key, newlist)

        # go through the list of just added jobs again
        for job in newList:  # there is no easy way to get newList from other data
            # patch job references in 'run', 'extend', ... keys
            for key in Lang.KEYS_WITH_JOB_REFS:
                if job.hasFeature(key):
                    patchFeature(job, key, renamedJobs)
        
        return
Beispiel #5
0
# -- Path-like Classes --------------------------------------------------------

class BasePath(object):

    def __init__ (self, val=None):
        self._data = None
        self.value(val)
    
    def value(self, val=None):
        mval = self._data
        if val != None:
            assert isinstance(val, types.StringTypes)
            self._data = unicode(val)
        return mval

URL          = NameSpace()
URL.PROT_SCH = 0
URL.NET_LOC  = 1
URL.PATH     = 2
URL.PARAMS   = 3
URL.QUERY    = 4
URL.FRAG     = 5

class OsPath(BasePath):

    def __init__(self, val=None):
        super(OsPath, self).__init__(val)
        self._data = os.path.normpath(self._data)

    def join(self, other):
        val = os.path.join(self.value(), other.value())
Beispiel #6
0
    def main():

        options = NameSpace()  # extensible object
        options.from_version
        options.makefile
        options.migrateHtml
        options.file
        options.classPath
        options.verbose
        options.classEncoding
        if not self.isValidVersion(options.from_version):
            raise RuntimeError( "\nERROR: The version '%s' is not a valid version string!\n" % options.from_version)


        if MIGRATION_ORDER[-1] == self.getNormalizedVersion(options.from_version):
            print "\n Nothing to do. Your application is up to date!\n"
            sys.exit()

        # to migrate a single file extract the class path
        if options.classPath == [] and options.file:
            options.classPath = [os.path.dirname(os.path.abspath(options.file))]

        if options.classPath == []:
            print """
ERROR: The class path is empty. Please specify the class pass using the
       --class-path option
"""
            sys.exit(0)


        neededUpdates = self.getNeededUpdates(options.from_version)

        # check whether tree bases modifications will be used
        hasPatchModule = False
        for version in neededUpdates:
            if self.getPatchModulePath(version) is not None:
                hasPatchModule = True
                break

        # set options for the loader and migrator
        options.classUri = []
        options.resourceInput = []
        options.resourceOutput = []
        options.cacheDirectory = None
        options.disableInternalCheck = False
        options.prettyPrint = True

        # migrate a single file
        if options.file:
            self.migrateSingleFile(options.file, options, neededUpdates)
            sys.exit(0)

        # build file database
        fileDb = {}
        listIndex = 0
        for path in options.classPath:
            loader.indexClassPath(path, listIndex, options, fileDb)
            listIndex += 1


        print"""
MIGRATION SUMMARY:

Current qooxdoo version:   %s
Upgrade path:              %s

Affected Classes:
    %s""" % (options.from_version, " -> ".join(neededUpdates), "\n    ".join(fileDb.keys()))

        if hasPatchModule:
            print """
WARNING: The JavaScript files will be pretty printed. You can customize the
         pretty printer using the PRETTY_PRINT_OPTIONS variable in your
         Makefile. You can find a complete list of pretty printing options
         at http://qooxdoo.org/documentation/articles/code_style."""

        choice = raw_input("""
NOTE:    It is advised to do a 'make distclean' before migrating any files.
         If you choose 'yes', a subprocess will be invoked to run distclean,
         and after completion you will be prompted if you want to
         continue with the migration. If you choose 'no', the making distclean
         step will be skipped (which might result in potentially unnecessary
         files being migrated).

Do you want to run 'make distclean' now? [yes] : """)

        if choice.lower() in ["j", "ja", "y", "yes", ""]:
            os.system("make distclean")

        choice = raw_input("""

WARNING: The migration process will update the files in place. Please make
         sure, you have a backup of your project. The complete output of the
         migration process will be logged to '%s'.

Do you want to start the migration now? [no] : """ % LOGFILE)

        if not choice.lower() in ["j", "y", "yes"]:
            sys.exit()

        # start migration
        self.setupLogging(options.verbose)
        fileLogger = logging.FileHandler(LOGFILE, "w")
        formatter = logging.Formatter('%(message)s')
        fileLogger.setFormatter(formatter)
        fileLogger.setLevel(logging.NOTSET)
        logging.getLogger().addHandler(fileLogger)

        if options.migrateHtml:
            htmlFiles = "."
        else:
            htmlFiles = None

        for version in neededUpdates:
            logging.info("")
            logging.info("UPGRADE TO %s" % (version))
            logging.info("----------------------------------------------------------------------------")

            self.handle(fileDb, options, self.getNormalizedVersion(version), htmlFiles, verbose=options.verbose)


        # patch makefile
        if not options.makefile is None:
          self.patchMakefile(options.makefile, MIGRATION_ORDER[-1], options.from_version)

        print """\n\nThe complete output of the migration process has been logged to the file '%s'.\n\n""" % LOGFILE
    def _integrateExternalConfig(self, extConfig, namespace, impJobsList=None, blockJobsList=None):

        # Some helper functions
        
        ##
        # Construct new job name for the imported job
        def createNewJobName(extJobEntry):
            if (importJobsList and extJobEntry in importJobsList 
                and isinstance(importJobsList[extJobEntry], types.DictType)):
                newjobname = namepfx + importJobsList[extJobEntry]['as']
            else:
                newjobname = namepfx + extJobEntry  # create a job name
            return newjobname

        ##
        # In case of a name collision, do some householding and return an
        # alternate job name.
        def clashPrepare(jobname):
            # import external job under different name
            console.warn("! Shadowing job \"%s\" with local one" % jobname)
            # construct a name prefix
            extConfigName = extConfig._fname or self.SHADOW_PREFIX
            extConfigName = os.path.splitext(os.path.basename(extConfigName))[0]
            # TODO: this might not be unique enough! (user could use extConfigName in 'as' param for other include)
            newjobname = extConfigName + self.COMPOSED_NAME_SEP + jobname
            return newjobname

        def clashProcess(clashCase):
            # check whether the local job is protected
            jobMap = self.getJobsMap()
            if ((Key.OVERRIDE_KEY not in jobMap) or
                (clashCase.name not in jobMap[Key.OVERRIDE_KEY])):
                # put shaddowed job in the local 'extend'
                if not newJob:
                    raise Error, "unsuitable new job"
                localjob = self.getJob(clashCase.name)
                extList = localjob.getFeature('extend', [])
                extList.append(newJob)
                localjob.setFeature('extend', extList)
                # add to config's shadowed list
                self._shadowedJobs[newJob] = localjob
            return

        ##
        # Fix job references, but only for the jobs from the just imported config
        def patchJobReferences(job, key, renamedJobs):
            newlist = []
            oldlist = job.getFeature(key)
            for jobentry in oldlist:
                # it's a string reference
                if isinstance(jobentry, types.StringTypes):
                    if Key.hasMacro(jobentry) and renamedJobs:
                        console.warn("Potential pitfall: Cannot rename job reference containing macros (%s#%s[\"%s\"]:%s)" \
                                        % (extConfig._fname, extJob.name, key, oldlist))
                    if jobentry in renamedJobs:
                        newlist.append(renamedJobs[jobentry])
                    else:
                        newlist.append(jobentry)
                # it's a Job() object
                else:
                    newlist.append(jobentry)
            job.setFeature(key, newlist)

        # -- Main --------------------------------------------------------------

        if namespace:
            namepfx = namespace + self.COMPOSED_NAME_SEP # job names will be namespace'd
        else:
            namepfx = ""         # job names will not be namespace'd

        renamedJobs = {}         # map for job renamings - done after all jobs have been imported
        clashCase   = NameSpace()  # to record a single clashing job name

        # Construct a map of import symbols (better lookup, esp. when aliased)
        importJobsList = {}
        if impJobsList:
            for e in impJobsList:
                if isinstance(e, types.StringTypes):
                    importJobsList[e]=None
                elif isinstance(e, types.DictType):  # {name: <name>, as: <alias>}
                    importJobsList[e['name']] = {'as': e['as']}
                else:
                    raise TypeError, "Illegal import entry: %s (Config: %s)" % (str(e), self._fname)

        # Merge global "let" -- currently disabled, see Bug#4126
        #extLet = extConfig.get(Key.LET_KEY, False)
        #if extLet:
        #    tmp = extLet.copy()
        #    tmp.update(self.get(Key.LET_KEY, {}))  # this should probably be deepMerge
        #    self.set(Key.LET_KEY, tmp)
        #    self.expandTopLevelKeys()  # we're making macro expansion in selected top-level keys eager

        # Go through the list of jobs to import
        newList     = []
        extJobsList = extConfig.getExportedJobsList()
        for extJobEntry in extJobsList:
            # Checks and preparations
            if importJobsList and extJobEntry not in importJobsList:
                continue
            if blockJobsList and extJobEntry in blockJobsList:
                continue
            newjobname = createNewJobName(extJobEntry)
            
            # Check for name clashes
            if self.hasJob(newjobname):
                clashCase.name_clashed = True
                clashCase.name = newjobname
                newjobname = clashPrepare(newjobname)
            else:
                clashCase.name_clashed = False  # reset

            # Now process the external job
            #   take essentially the external job into the local joblist
            extJob = extConfig.getJob(extJobEntry)  # fetch this job
            if not extJob:
                raise RuntimeError, "No such job: \"%s\" while including config: \"%s\")" % (extJobEntry, extConfig._fname)
            newJob = Job(newjobname, {}, self._console, self) # fake as local job, for _includeGlobalLet to run locally
            newJob.includeGlobalLet()  # have to draw in local let before all the external let's are processed
            newJob.mergeJob(extJob)    # now merge in the external guy
            newJob.setConfig(extJob.getConfig()) # retain link to original config
            if (newjobname != extJobEntry  # adapt modified names; otherwise, delay name resolution until resolveExtendsAndRun()
                and not clashCase.name_clashed):       # keep job references if there is shadowing
                renamedJobs[extJobEntry] = newjobname  # keep string reference for later binding
            self.addJob(newjobname, newJob)         # and add it
            newList.append(newJob)         # memorize jobs added from extConfig for later

            # Now process a possible name clash
            if clashCase.name_clashed:
                clashProcess(clashCase)
        
        # Fix job references, but only for the jobs from the just imported config
        # go through the list of just added jobs again
        for job in newList:  # there is no easy way to get newList from other data
            # patch job references in 'run', 'extend', ... keys
            for key in Key.KEYS_WITH_JOB_REFS:
                if job.hasFeature(key):
                    patchJobReferences(job, key, renamedJobs)
        
        return
Beispiel #8
0

class BasePath(object):
    def __init__(self, val=None):
        self._data = None
        self.value(val)

    def value(self, val=None):
        mval = self._data
        if val != None:
            assert isinstance(val, types.StringTypes)
            self._data = unicode(val)
        return mval


URL = NameSpace()
URL.PROT_SCH = 0
URL.NET_LOC = 1
URL.PATH = 2
URL.PARAMS = 3
URL.QUERY = 4
URL.FRAG = 5


class OsPath(BasePath):
    def __init__(self, val=None):
        super(OsPath, self).__init__(val)
        self._data = os.path.normpath(self._data)

    def join(self, other):
        val = os.path.join(self.value(), other.value())
from misc.NameSpace import NameSpace
from generator.action import ActionLib
from generator import Context

log_levels = {
    "debug": 10,
    "info": 20,
    "warning": 30,
    "error": 40,
    "fatal": 50,
}
log_level = "error"
AR_Check_Url = "/_active_reload/sentinel.json"
AR_Script_Url = "/_active_reload/active_reload.js"

live_reload = NameSpace()


class RequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
    # idea: restrict access from 'localhost' only (parse RequestHandler.request),
    # to prevent exposing the local file system to outsiders

    # @overridden from BaseHTTPServer
    def log_request(self, code='-', size='-'):
        if log_levels[log_level] <= log_levels['info']:
            self.log_message('"%s" %s %s', self.requestline, str(code),
                             str(size))

    # @overridden from BaseHTTPServer
    def log_error(self, format, *args):
        if log_levels[log_level] <= log_levels['error']:
Beispiel #10
0
    def main():

        options = NameSpace()  # extensible object
        options.from_version
        options.makefile
        options.migrateHtml
        options.file
        options.classPath
        options.verbose
        options.classEncoding
        if not self.isValidVersion(options.from_version):
            raise RuntimeError( "\nERROR: The version '%s' is not a valid version string!\n" % options.from_version)


        if MIGRATION_ORDER[-1] == self.getNormalizedVersion(options.from_version):
            print "\n Nothing to do. Your application is up to date!\n"
            sys.exit()

        # to migrate a single file extract the class path
        if options.classPath == [] and options.file:
            options.classPath = [os.path.dirname(os.path.abspath(options.file))]

        if options.classPath == []:
            print """
ERROR: The class path is empty. Please specify the class pass using the
       --class-path option
"""
            sys.exit(0)


        neededUpdates = self.getNeededUpdates(options.from_version)

        # check whether tree bases modifications will be used
        hasPatchModule = False
        for version in neededUpdates:
            if self.getPatchModulePath(version) is not None:
                hasPatchModule = True
                break

        # set options for the loader and migrator
        options.classUri = []
        options.resourceInput = []
        options.resourceOutput = []
        options.cacheDirectory = None
        options.disableInternalCheck = False
        options.prettyPrint = True

        # migrate a single file
        if options.file:
            self.migrateSingleFile(options.file, options, neededUpdates)
            sys.exit(0)

        # build file database
        fileDb = {}
        listIndex = 0
        for path in options.classPath:
            loader.indexClassPath(path, listIndex, options, fileDb)
            listIndex += 1


        print"""
MIGRATION SUMMARY:

Current qooxdoo version:   %s
Upgrade path:              %s

Affected Classes:
    %s""" % (options.from_version, " -> ".join(neededUpdates), "\n    ".join(fileDb.keys()))

        if hasPatchModule:
            print """
WARNING: The JavaScript files will be pretty printed. You can customize the
         pretty printer using the PRETTY_PRINT_OPTIONS variable in your
         Makefile. You can find a complete list of pretty printing options
         at http://qooxdoo.org/documentation/articles/code_style."""

        choice = raw_input("""
NOTE:    It is advised to do a 'make distclean' before migrating any files.
         If you choose 'yes', a subprocess will be invoked to run distclean,
         and after completion you will be prompted if you want to
         continue with the migration. If you choose 'no', the making distclean
         step will be skipped (which might result in potentially unnecessary
         files being migrated).

Do you want to run 'make distclean' now? [yes] : """)

        if choice.lower() in ["j", "ja", "y", "yes", ""]:
            os.system("make distclean")

        choice = raw_input("""

WARNING: The migration process will update the files in place. Please make
         sure, you have a backup of your project. The complete output of the
         migration process will be logged to '%s'.

Do you want to start the migration now? [no] : """ % LOGFILE)

        if not choice.lower() in ["j", "y", "yes"]:
            sys.exit()

        # start migration
        self.setupLogging(options.verbose)
        fileLogger = logging.FileHandler(LOGFILE, "w")
        formatter = logging.Formatter('%(message)s')
        fileLogger.setFormatter(formatter)
        fileLogger.setLevel(logging.NOTSET)
        logging.getLogger().addHandler(fileLogger)

        if options.migrateHtml:
            htmlFiles = "."
        else:
            htmlFiles = None

        for version in neededUpdates:
            logging.info("")
            logging.info("UPGRADE TO %s" % (version))
            logging.info("----------------------------------------------------------------------------")

            self.handle(fileDb, options, self.getNormalizedVersion(version), htmlFiles, verbose=options.verbose)


        # patch makefile
        if not options.makefile is None:
          self.patchMakefile(options.makefile, MIGRATION_ORDER[-1], options.from_version)

        print """\n\nThe complete output of the migration process has been logged to the file '%s'.\n\n""" % LOGFILE