TinyMake in Python

A first tentative stab at porting TinyMake to Python…
[source code also available here]

import os
from os import stat
class tinymake:
    """ """

    changed = ()
    sources = ()
    target = None

    _prerequisites_for_target = {}
    _commands_for_target = {}
    _first = None
    _cachedsourcetimes = {}

    def postorderwalk(self,node,children,store,visited) :
        """ """
        for n in visited :
            if node == n:
                return store

        visited.append(node)

        kids = children(node)
        
        for child in kids:
            self.postorderwalk(child,children,store,visited)

        store.append(node)

        return store
    
    def depends (self, target, store, visited):
        """ """
        def children (node):
            """ """
            if self._prerequisites_for_target.has_key(node):
                return self._prerequisites_for_target[node]

            return []
        return self.postorderwalk(target,children,store,visited)
        
    def file (self, target, prerequisites, code):
        """ """
        if self._first == None:
            self._first = target
        
        if prerequisites:
            self._prerequisites_for_target[target] = prerequisites

        if code :
            self._commands_for_target[target] = code
            
    def sourcetimes (self,sources):
        """ """
        result = {}
        for source in sources:
            value = None
            if self._commands_for_target.has_key(source) or self._prerequisites_for_target.has_key(source):
                #
                # the source file is also mentioned as a target
                #
                filestats = os.stat(source)
                value = filestats.st_mtime
            else :
                #
                # the sourcefile is not mentioned as a target
                # (it is pure)
                #
                if not self._cachedsourcetimes.has_key(source):
                    filestats = os.stat(source)
                    self._cachedsourcetimes = filestats.st_mtime
                    
                value = self._cachedsourcetimes
            result = value

        return result

    def make (self, *targets):
        """ """
        result = []
        if not targets:
            
            targets = [self._first]

        execute = False
        
        for t in targets:
            
            files = self.depends(t,[],[])
            
            files_i_can_build = []
            for file in files:
                if self._commands_for_target.has_key(file):
                    files_i_can_build.append(file)
            
            for file_i_can_build in files_i_can_build:
                
                self.target = file_i_can_build
                self.changed = []
                self.sources = []
                if self._prerequisites_for_target.has_key(self.target):
                    
                    self.sources = self._prerequisites_for_target[self.target]
                    self.changed = self.sources

                execute = True

                if os.path.exists(self.target):
                    
                    filestats = os.stat(self.target)
                    targettime = filestats.st_mtime
                    self._sourcetimes = self.sourcetimes(self.sources)
                    self.changed = []
                    for source in self.sources:
                        if self._sourcetimes > targettime:
                            self.changed.append(source)
                    if len(self.changed) > 0:
                        execute = True
                    else :
                        execute = False
                    
                if execute:
                    
                    f = self._commands_for_target[self.target];
                    f(self.target,self.changed,self.sources)
                    result.append(self.target)
                
                else :
                    print "%s is up to date\n"  % (file_i_can_build)

            return result

To use tinymake…

from tinymake import tinymake

""" MAIN PROGRAM """

def testing (t,c,s):
    
    print "target: %s, changed: %s, sources: %s" % (t,c,s)
    f = open(t,"w")
    print >>f, "OK"
    f.close()
    

tm = tinymake()

tm.file("c:/scratch/o.txt",["c:/scratch/i1.txt","c:/scratch/i2.txt"],testing )

tm.make()

It probably isn’t very pythonic but I’m posting it here as a placeholder. Python’s lack of anonymous blocks is shocking.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: