Depend.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 » Depend.py
# Part of the A-A-P recipe executive: Dependency rules

# 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


# A Depend object contains:
#  targetlist   - dictlist of targets
#  build_attr   - dictlist of build attributes (right after the ":")
#  sourcelist   - dictlist of sources
#  rpstack      - RecPos stack for where the commands were defined
#  commands     - string of command lines
#  builddir     - directory where "commands" are to be executed
#  buildrecdict - the recdict of the recipe where it was defined or None
#  use_recdict  - recdict to be used when executing build commands
#  matchstr     - for a rule: the string that matched %
#  startup      - non-zero for a dependency defined in a startup recipe
#
# Illustration:
#       targetlist : {build_attr} sourcelist
#               commands

import os
import os.path
import string

from Error import *
from Util import *
from Message import *

class Depend:
    def __init__(self, targetlist, build_attr, sourcelist,
                     work, rpstack, commands, builddir = None, recdict = None):
        self.targetlist = targetlist
        self.build_attr = build_attr
        self.sourcelist = sourcelist
        self.rpstack = rpstack

        self.commands = commands
        if builddir is None:
            self.builddir = os.getcwd()
        else:
            self.builddir = builddir
        self.buildrecdict = recdict
        self.keep_current_scope = 0     # Current scope overrules scope of
                                        # build commands; used for rules and
                                        # actions.
        self.use_recdict = None
        self.matchstr = ''
        self.startup = 0
        self.in_use = 0

        # Add nodes for all sources and targets, with a pointer back to the
        # node.  Also carries over the attributes to the node.
        work.dictlist_nodes(self.targetlist)
        work.dictlist_nodes(self.sourcelist)

    def __str__(self):
        from Dictlist import dictlist2str,dictlistattr2str

        return (dictlist2str(self.targetlist)
                    + " : "
                    + dictlistattr2str(self.build_attr)
                    + dictlist2str(self.sourcelist)
                    + "\n" + self.commands)

    def get_scope_names(self, work):
        """
        Get the list of scope names to be used for build commands.  First the
        one specified as build attribute.  A scope specified for a source
        is appended.
        """
        # Attribute on dependency itself.
        xscope = self.build_attr.get("scope")
        if xscope:
            ret = [ xscope ]
        else:
            ret = []

        for s in self.sourcelist:
            if s.get("scope"):
                # Attribute on source mentioned for dependency.
                ret.append(s["scope"])
            else:
                node = work.find_node(s["name"])
                if node and node.attributes.get("scope"):
                    # Attribute on source node.
                    ret.append(node.attributes["scope"])
        return ret


def depend_auto(work, recdict, node, node_dict, level):
    """
    Find the implied dependencies for "node".
    "node_dict" contains attributes specified for the node specifically for the
    current dependency.  They overrule attributes from the node itself.
    The dependencies are returned in node.autodep_dictlist.
    If "node" changed since last time, regenerate the dependencies.
    """
    # Previously we returned quickly when the automatic dependencies were
    # already generated, because we cannot be sure they are still up-to-date.
    # Changed attributes might matter.

    # Don't generate automatic dependencies when "AUTODEPEND" is "off".
    if (recdict["_no"].get("AUTODEPEND") == "off"
            or (node.attributes.get("autodepend") == "off"
                or node_dict.get("autodepend") == "off")):
        node.autodep_dictlist = []
        return

    # Get the file type.
    ftype = node_dict.get("filetype")
    if not ftype:
        ftype = node.get_ftype(recdict)
    if not ftype:
        msg_depend(recdict,
                        _('Unknown type of file, no dependency check for "%s"')
                                                    % node.short_name(), level)
        node.autodep_dictlist = []
        return

    # A compressed or ".in" file is not checked.
    if ftype == "ignore":
        node.autodep_dictlist = []
        return

    # Trigger the rule to produce a dependency recipe for this node.
    # This will also update node.autodep_dictlist when node.autodep_recursive
    # is set.
    from DoBuild import build_autodepend
    recipe = build_autodepend(work, recdict, ftype, node, node_dict, level)

    # return silently when no dependencies could be generated
    if not recipe:
        node.autodep_dictlist = []
        return

    if not os.path.exists(recipe.name):
        msg_warning(recdict,
                      _('Dependency file was not created: "%s"') % recipe.name)
        node.autodep_dictlist = []
        return

    # Read the generated recipe file when not done already.
    if not node.autodep_recursive:
        node.autodep_dictlist = read_auto_depend(recdict, recipe,
                                                               node.get_name())


def read_auto_depend(recdict, recipe, skipname):
    """
    Read a generated recipe file from node "recipe".
    We only want the part after the ":", the item before it may be wrong
    (gcc generates foo.o: foo.c foo.h).
    Ignore "skipname".
    Don't read the recipe as a normal recipe, that would cause trouble with
    things we don't want to find in there. 
    """
    try:
        fd = open(recipe.name)
    except:
        msg_error(recdict, _('Cannot open "%s" for reading.') % recipe.name)
        return []

    from ParsePos import ParsePos
    from RecPos import RecPos
    rpstack = [ RecPos(recipe.name) ]

    # create an object to contain the file position
    fp = ParsePos(rpstack, file = fd)
    fp.nextline()           # read the first (and only) line
    if fp.line is None:
        msg_depend(recdict, _('Nothing to read from "%s".') % recipe.name)
        return []
    i = string.find(fp.line, ":")
    if os.name != "posix" and i == 1:       # DOS filename: "C:\dir\foo.c"
        i = string.find(fp.line, ":", 2)
    if i < 0:
        msg_error(recdict, _('No colon found in "%s".') % recipe.name)
        return []

    autodep_dictlist = []
    if i + 1 < fp.line_len:
        # Need to convert names with backslash-space to quoted name.
        nl = ''
        i = i + 1
        item = ''
        had_bsl = 0
        had_q = 0
        line_len = len(fp.line)
        while 1:
            if i >= line_len or is_white(fp.line[i]):
                if item:
                    # End of an item, append it to "nl" with or without quotes.
                    if nl:
                        nl = nl + ' '
                    if had_bsl == 1:
                        nl = nl + enquote(item)
                    else:
                        nl = nl + item
                if i >= line_len:
                    break
                had_bsl = 0
                had_q = 0
                item = ''
            elif (fp.line[i] == '\\' and i + 1 < line_len
                                   and is_white(fp.line[i + 1]) and not had_q):
                i = i + 1
                had_bsl = 1     # found a backslashed space or tab
                item = item + fp.line[i]
            elif fp.line[i] == '"' or fp.line[i] == "'":
                had_q = 1       # don't recognize backslash after a quote
                item = item + fp.line[i]
            else:
                item = item + fp.line[i]
            i = i + 1

        from Dictlist import str2dictlist
        autodep_dictlist = str2dictlist(rpstack, nl)

        # Make the path absolute (that's faster, SRCPATH won't be used).
        # Remove the node itself.
        for k in autodep_dictlist[:]:
            k["name"] = os.path.abspath(k["name"])
            if k["name"] == skipname:
                autodep_dictlist.remove(k)

    # Check for trailing text.
    fp.nextline()
    if not fp.line is None:
        msg_note(recdict, _('Found trailing text in "%s"') % recipe.name)

    fd.close()
    return autodep_dictlist



# 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.