~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to py/test/terminal/remote.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import generators
 
2
import py
 
3
from py.__.test.session import Session
 
4
from py.__.test.terminal.out import getout
 
5
from py.__.test.outcome import Failed, Passed, Skipped
 
6
 
 
7
def checkpyfilechange(rootdir, statcache={}):
 
8
    """ wait until project files are changed. """
 
9
    def fil(p): 
 
10
        return p.ext in ('.py', '.c', '.h')
 
11
    #fil = lambda x: x.check(fnmatch='*.py')
 
12
    def rec(p):
 
13
        return p.check(dotfile=0)
 
14
    changed = False
 
15
    for path in rootdir.visit(fil, rec):
 
16
        oldstat = statcache.get(path, None)
 
17
        try:
 
18
            statcache[path] = curstat = path.stat()
 
19
        except py.error.ENOENT:
 
20
            if oldstat:
 
21
                del statcache[path]
 
22
                print "# WARN: race condition on", path
 
23
        else:
 
24
            if oldstat:
 
25
               if oldstat.mtime != curstat.mtime or \
 
26
                  oldstat.size != curstat.size:
 
27
                    changed = True
 
28
                    print "# MODIFIED", path
 
29
            else:
 
30
                changed = True
 
31
    return changed
 
32
 
 
33
def getfailureitems(failures): 
 
34
    l = []
 
35
    for rootpath, names in failures:
 
36
        root = py.path.local(rootpath)
 
37
        if root.check(dir=1):
 
38
            current = py.test.collect.Directory(root).Directory(root)
 
39
        elif root.check(file=1):
 
40
            current = py.test.collect.Module(root).Module(root)
 
41
        # root is fspath of names[0] -> pop names[0]
 
42
        # slicing works with empty lists
 
43
        names = names[1:]
 
44
        while names: 
 
45
            name = names.pop(0) 
 
46
            try: 
 
47
                current = current.join(name)
 
48
            except NameError: 
 
49
                print "WARNING: could not find %s on %r" %(name, current) 
 
50
                break 
 
51
        else: 
 
52
            l.append(current) 
 
53
    return l
 
54
 
 
55
class RemoteTerminalSession(Session):
 
56
    def __init__(self, config, file=None):
 
57
        super(RemoteTerminalSession, self).__init__(config=config)
 
58
        self._setexecutable()
 
59
        if file is None:
 
60
            file = py.std.sys.stdout 
 
61
        self._file = file
 
62
        self.out = getout(file)
 
63
 
 
64
    def _setexecutable(self):
 
65
        name = self.config.option.executable
 
66
        if name is None:
 
67
            executable = py.std.sys.executable 
 
68
        else:
 
69
            executable = py.path.local.sysfind(name)
 
70
            assert executable is not None, executable 
 
71
        self.executable = executable 
 
72
 
 
73
    def main(self):
 
74
        rootdir = self.config.topdir 
 
75
        wasfailing = False 
 
76
        failures = []
 
77
        while 1:
 
78
            if self.config.option.looponfailing and (failures or not wasfailing): 
 
79
                while not checkpyfilechange(rootdir):
 
80
                    py.std.time.sleep(4.4)
 
81
            wasfailing = len(failures)
 
82
            failures = self.run_remote_session(failures)
 
83
            if not self.config.option.looponfailing: 
 
84
                break
 
85
            print "#" * 60
 
86
            print "# looponfailing: mode: %d failures args" % len(failures)
 
87
            for root, names in failures:
 
88
                name = "/".join(names) # XXX
 
89
                print "Failure at: %r" % (name,) 
 
90
            print "#    watching py files below %s" % rootdir
 
91
            print "#                           ", "^" * len(str(rootdir))
 
92
        return failures
 
93
 
 
94
    def _initslavegateway(self):
 
95
        print "* opening PopenGateway: ", self.executable 
 
96
        topdir = self.config.topdir
 
97
        return py.execnet.PopenGateway(self.executable), topdir
 
98
 
 
99
    def run_remote_session(self, failures):
 
100
        gw, topdir = self._initslavegateway()
 
101
        channel = gw.remote_exec("""
 
102
            from py.__.test.terminal.remote import slaverun_TerminalSession
 
103
            slaverun_TerminalSession(channel) 
 
104
        """, stdout=self.out, stderr=self.out) 
 
105
        try:
 
106
            print "MASTER: initiated slave terminal session ->"
 
107
            repr = self.config._makerepr(conftestnames=[])
 
108
            channel.send((str(topdir), repr, failures))
 
109
            print "MASTER: send start info, topdir=%s" % (topdir,)
 
110
            try:
 
111
                return channel.receive()
 
112
            except channel.RemoteError, e:
 
113
                print "*" * 70
 
114
                print "ERROR while waiting for proper slave startup"
 
115
                print "*" * 70
 
116
                print e
 
117
                return []
 
118
        finally:
 
119
            gw.exit()
 
120
 
 
121
def slaverun_TerminalSession(channel):
 
122
    """ we run this on the other side. """
 
123
    print "SLAVE: initializing ..."
 
124
    topdir, repr, failures = channel.receive()
 
125
    print "SLAVE: received configuration, using topdir:", topdir
 
126
    config = py.test.config 
 
127
    config._initdirect(topdir, repr, failures)
 
128
    config.option.session = None
 
129
    config.option.looponfailing = False 
 
130
    config.option.usepdb = False 
 
131
    config.option.executable = None
 
132
    if failures:
 
133
        config.option.verbose = True
 
134
 
 
135
    session = config.initsession()
 
136
    session.shouldclose = channel.isclosed 
 
137
    print "SLAVE: starting session.main()"
 
138
    session.main()
 
139
    failures = session.getitemoutcomepairs(Failed)
 
140
    failures = [config.get_collector_trail(item) for item,_ in failures]
 
141
    channel.send(failures)