Main.py :  » Build » A-A-P » aap-1.091 » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Build » A A P 
A A P » aap 1.091 » Main.py
#! /usr/bin/env python
# Part of the A-A-P recipe executive: The main function.

# Copyright (C) 2002-2003 Stichting NLnet Labs
# Permission to copy and use this file is specified in the file COPYING.
# If this file is missing you can find it here: http://www.a-a-p.org/COPYING

# Main Python code that executes an A-A-P recipe

import sys
from traceback import print_exception,format_exception

# Each phase of executing a recipe is done by one module
from DoAddDef import doadddef
from DoArgs import doargs
from DoBuild import dobuild
from DoRead import doread
from DoInstall import doinstall

from Cache import dump_cache
from Error import *
from Sign import sign_write_all,sign_clear_all
from Util import *
import Global
from Message import *

# Globals
exit_status = 0             # exit status; default is zero (success)
exit_info = None            # exception stack when something went wrong.

def error_msg(recdict, msg):
    """Print an error message and set the exit status to one."""
    global exit_status
    msg_error(recdict, msg)
    if exit_status == 0:
        exit_status = 1

profiling = 0

def do_the_work(argv, find_recipe, commands):
    """Common function for main() and execute().
       "argv" is the list of command line arguments (excluding the program
       name).
       When "find_recipe" is non-zero, search for a recipe to load.
       When "commands" is None, execute the specified or default target(s).
       When "commands" is empty, do nothing.
       When "commands" is a non-empty string, execute these commands.
       Returns an error message and a work object.
       exit_status is set to a non-zero value when something failed.
    """
    global exit_status, exit_info
    exit_status = 0
    exit_info = None

    # We require Python 1.5 or later.
    if sys.version[0] == '1' and int(sys.version[2]) < 5:
        exit_status = 1
        return "A-A-P requires Python version 1.5 or later.", None

    # Need to know the directory of this module.  But __file__ isn't defined
    # when executed directly, then use argv[0] instead, see below.
    if not Global.aap_rootdir:
        Global.set_aap_rootdir(os.path.abspath(os.path.dirname(__file__)))

    # Internationalisation inits: setlocale and gettext.
    i18n_init()

    #
    # Do the main work.
    #
    msg = None
    work = None

    try:
        # 1. Process the command line arguments.
        Global.cmd_args = doargs(argv)

        if Global.cmd_args.has_option("verbose"):
            Global.cmd_args.printit()
        
        # When profiling is requested and it wasn't started yet, start all over
        # with profiling enabled.
        global profiling
        if not profiling and Global.cmd_args.has_option("profile"):
            profiling = 1
            import profile
            prof = profile.Profile()
            try:
                res = prof.runcall(do_the_work, argv, find_recipe, commands)
            finally:
                prof.dump_stats(Global.cmd_args.options.get("profile"))
            return res

        # When "--install pkg" is used: install a package.
        if Global.cmd_args.has_option("install"):
            work = doinstall(Global.cmd_args.options.get("install"))
        else:
            # 2. Read the recipe and included recipes.  Assignments and commands
            #    are executed directly, rules and dependencies are stored.
            #    "work" is a Work object with collected items from the recipe.
            work = doread(find_recipe)

            # 3. Add the default dependencies
            doadddef(work, work.recdict, 1)

            # 4. Build each target or execute the commands.
            if commands:
                from ParsePos import ParsePos
                from RecPos import RecPos
                from Process import Process

                fp = ParsePos([ RecPos(_('execute()'), 0) ],
                                                      string = commands + '\n')
                Process(fp, work.recdict, 0)
            elif commands is None:
                dobuild(work)

    except NormalExit, r:  # planned exit
        exit_status = r
    except SystemExit, r:
        exit_status = r
        msg = _("Aborted")
    except KeyboardInterrupt:
        exit_status = 1
        msg = _("Interrupted")
    except UserError, e:
        exit_status = 1
        msg = e.args
    except SyntaxError, e:
        exit_status = 1
        exit_info = sys.exc_info()
        msg = _("Syntax error") + str(e)
    except:
        exit_status = 1
        exit_info = sys.exc_info()
        msg = _("Internal Error")

    if work:
        # Dump entries for the downloaded files.
        dump_cache(work.recdict)

        # Dump the sign files.  Clear all signatures (for any next run).
        sign_write_all(work.recdict)
        sign_clear_all()

        # Close any subshell for installing packages.
        from Port import close_sushell
        close_sushell(work.recdict)

        # Close any root shell.
        close_rootshell(work.recdict)

        # Cleanup for any configure checks.
        import DoConf
        DoConf.cleanup(work.recdict)

    if msg == None:
        return None, work
    else:
        return msg[0], work


def main(setroot = 0):
    """
    The main function to execute an A-A-P recipe.
    """

    if setroot:
        # We need to know the location of our modules (find ccskim there).
        try:
            progname = os.path.realpath(sys.argv[0])
        except:
            # Doesn't have os.path.realpath(), it's new in Python 2.2
            # Use our copy of it.
            try:
                progname = myrealpath(sys.argv[0])
            except:
                # Still not working?  Fall back to using abspath().
                progname = os.path.abspath(sys.argv[0])

        Global.set_aap_rootdir(os.path.dirname(progname))

        # When started with a relative path and changing directories we still
        # need to be able to find our modules.
        sys.path.append(Global.aap_rootdir)

    # Do the work.
    msg, work = do_the_work(sys.argv[1:], 1, None)
    handle_work_done(msg, work)
    sys.exit(exit_status)


def handle_work_done(msg, work):
    """Handle errors after calling do_the_work()."""
    if msg:
        if work:
            error_msg(work.recdict, msg)
        else:
            error_msg(None, msg)
        if exit_info:
            print_exception(exit_info[0], exit_info[1], exit_info[2])
            error_msg(None, string.join(format_exception(exit_info[0],
                                                  exit_info[1], exit_info[2])))

    # Get the log file name before it's cleared by stopping the log.
    # Stop the log before the message, so that it doesn't get into the log.
    if exit_status:
        if msg_logname():
            logmsg = "All messages are in the logfile: " + msg_logname()
        else:
            logmsg = ''
    msg_stoplog()

    if exit_status and logmsg:
        if work:
            msg_info(work.recdict, logmsg)
        else:
            msg_info(None, logmsg)


# Return a canonical path (i.e. the absolute location of a file on the
# filesystem).  This is from os.path of Python 2.2.
def myrealpath(filename):
    """Return the canonical path of the specified filename, eliminating any
    symbolic links encountered in the path."""
    filename = os.path.abspath(filename)

    bits = ['/'] + filename.split('/')[1:]
    for i in range(2, len(bits)+1):
        component = apply(os.path.join, tuple(bits[0:i]))
        if os.path.islink(component):
            resolved = os.readlink(component)
            (adir, afile) = os.path.split(component)
            resolved = os.path.normpath(os.path.join(adir, resolved))
            newpath = apply(os.path.join, tuple([resolved] + bits[i:]))
            return myrealpath(newpath)

    return filename


# When executed directly, call the main function.
if __name__ == '__main__':
    main(1)


#
# Other programs may call this funtion to execute one or more recipe commands.
# For example: execute(":do view thisfile")
#
def execute(commands, argv = [], find_recipe = 0):
    """Execute recipe commands "commands".  See do_the_work() for details about
       "commands".
       "argv" is a list of command line arguments.
       "find_recipe" is non-zero to find a default recipe.
       Returns an error message or None."""
    msg, work = do_the_work(argv, find_recipe, commands)

    if exit_info:
        print msg
        print_exception(exit_info[0], exit_info[1], exit_info[2])

    msg_stoplog()

    return msg


#
# Other programs may call this function to fetch a list of files.
# Uses the "main.aap" recipe, unless "argv" specifies another recipe to use.
#
def fetch(fnames, argv = []):
    """Fetch files in list "fnames".
       "argv" is a list of command line arguments.
       Will search for a default recipe if none is specified.
       Returns an error message or None."""
    from Dictlist import list2str
    return execute(":fetch %s" % list2str(fnames), argv, 1)


#
# Other programs may call this function to obtain the list of nodes and
# recdict.  It was added to be used by the IDE.
# Uses the "main.aap" recipe, unless "argv" specifies another recipe to use.
#
def get_nodelist(argv = []):
    """Obtain the information from the recipe specified with "argv" or the
       default recipe.
       Return a tuple with the list of nodes and a dictionary for the global
       variables."""
    msg, work = do_the_work(argv, 1, '')
    handle_work_done(msg, work)

    if not work:
        return [], {}
    return work.nodes.values(), work.recdict


def get_actionlist(argv = []):
    """Obtain a dictionary that lists the actions supported for each file
       type.  Can be used to make sure that executing the action will actually
       work.  "argv" is usually empty."""
    msg, work = do_the_work(argv, 0, '')
    handle_work_done(msg, work)

    if not work:
        return {}

    import Action
    return Action.action_get_list()



# vim: set sw=4 et sts=4 tw=79 fo+=l:
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.