[python 2.7/buildbot]

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • DutchNutcase
  • Registratie: Augustus 2005
  • Niet online
Jullie moeten mij vergeven voor de misschien ietwat domme vraag, maar ik kom er niet meer uit. Ik ben zelf geen Python programmeur, maar een wetenschappelijke FORTRAN programmeur. Doordat ik ook ben gebombardeerd tot Configurations Manager voor onze programma's (chem1d, trot en nog wat andere dingen) ben ik het afgelopen jaar in aanraking gekomen met Python via buildbot. Eerst had ik een vrij statische configuratie in mijn master.cfg, maar door enkele voorbeelden ben ik er van overtuigd geraakt dat een master.cfg als python programma beter is. Dit gaat vrij aardig.

Ik loop alleen tegen iets geks aan. Ik heb een eigen test class geschreven, die als extensie dient van de buildbot Test class. Daarbij geef ik in de __init__ methode enkele parameters mee, die ik als attributes van de instantie wil bewaren. Dit zijn de variabelen prog -> self.prog, system -> self.separator en testNumber -> self.testNumber. Het gekke is dat self.prog en self.separator netjes onthouden worden in de instantie, maar dit gebeurt niet bij self.testNumber. Zie de code hieronder:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class Chem1dTest(Test):
    def __init__(self, prog=None, system=None, testNumber=None, **kwargs):
        if prog:
            self.prog = prog
        elif hasattr(self, 'prog'):
            prog = self.prog
        else:
            self.prog = 'chem1d'
        if system:
            if 'win' in system:
                self.separator = '\\'
            else:
                self.separator = '/'
        elif hasattr(self, 'separator'):
            system = None
        else:
            self.separator = '/'
        if testNumber:
            self.testNumber = testNumber

        f = open('/tmp/debug.log', 'a')
        f.write(str(prog))
        f.write('\n')
        f.write(str(self.prog))
        f.write('\n')
        f.write(str(system))
        f.write('\n')
        f.write(str(self.separator))
        f.write('\n')
        f.write(str(testNumber))
        f.write('\n')
        if hasattr(self, 'testNumber'):
            f.write(str(self.testNumber))
            f.write('\n')

        f.close()

        if self.prog == 'chem1d':
            kwargs['command'] = ['..%s..%sbin%schem1d' % (self.separator, self.separator, self.separator)]
            kwargs['workdir'] = 'build/test/case%s' % (str(self.testNumber))
            kwargs['description'] = ['Running', 'test', 'case', str(self.testNumber)]
            kwargs['descriptionDone'] = ['Test', str(self.testNumber)]
        elif self.prog == 'trot':
            kwargs['command'] = ['..%s..%sbin%strot' % (self.separator, self.separator, self.separator)]
            kwargs['workdir'] = 'build/test/trot'
            kwargs['description'] = ['Running', 'trot', 'integration', 'test']
            kwargs['descriptionDone'] = ['Trot', 'test']

        Test.__init__(self, **kwargs)

def make_tests(system=None, tests=None):
    if system == None:
        system='linux-x86_64'

    if tests == None:
        tests = 4

    testSteps = []

    for i in range(1, tests+1):
        testSteps.append(Chem1dTest(
            system=system, testNumber=i
        ))

    testSteps.append(Chem1dTest(
        prog='trot', system=system
    ))

    return testSteps

Als ik in de debug file kijk zie ik dat wanneer ik buildbot herstart alles netjes geset word, maar zodra ik op "rebuild" klik alleen self.testNumber problemen geeft.

/tmp/debug.log tijdens een restart:
None
chem1d
win32
\
1
1
None
chem1d
win32
\
2
2
None
chem1d
win32
\
3
3
None
chem1d
win32
\
4
4
trot
trot
win32
\
None
None
chem1d
linux-x86_64
/
1
1
None
chem1d
linux-x86_64
/
2
2
None
chem1d
linux-x86_64
/
3
3
None
chem1d
linux-x86_64
/
4
4
trot
trot
linux-x86_64
/
None
None
chem1d
linux-i386
/
1
1
None
chem1d
linux-i386
/
2
2
None
chem1d
linux-i386
/
3
3
None
chem1d
linux-i386
/
4
4
trot
trot
linux-i386
/
None
en als ik "rebuild":
None
chem1d
None
/
None

En buildbot's twistd.log geeft de volgende fout aan:
2012-02-20 12:25:19+0100 [-] <Build chem1d linux-x86_64 nightly build>.startBuild
2012-02-20 12:25:19+0100 [-] error while creating step, factory=chem1dbbconfig.buildsteps.Chem1dTest, args={'lazylogfiles': False, 'workdir': 'build/test/case1', 'warningPattern': None, 'description': ['Running', 'test', 'case', '1'], 'descriptionDone': ['Test', '1'], 'log_eval_func': None, 'suppressionFile': None, 'logfiles': {}, 'usePTY': 'slave-config', 'maxWarnCount': None, 'command': ['../../bin/chem1d'], 'directoryEnterPattern': None, 'directoryLeavePattern': None, 'warningExtractor': None}
2012-02-20 12:25:19+0100 [-] Build.setupBuild failed
2012-02-20 12:25:19+0100 [-] Unhandled Error
        Traceback (most recent call last):
          File "/usr/local/lib/python2.6/dist-packages/Twisted-10.2.0-py2.6-linux-x86_64.egg/twisted/internet/defer.py", line 542, in _runCallbacks
            current.result = callback(current.result, *args, **kw)
          File "/usr/local/lib/python2.6/dist-packages/Twisted-10.2.0-py2.6-linux-x86_64.egg/twisted/internet/defer.py", line 891, in gotResult
            _deferGenerator(g, deferred)
          File "/usr/local/lib/python2.6/dist-packages/Twisted-10.2.0-py2.6-linux-x86_64.egg/twisted/internet/defer.py", line 866, in _deferGenerator
            result = g.next()
          File "/usr/local/lib/python2.6/dist-packages/buildbot-0.8.5-py2.6.egg/buildbot/process/builder.py", line 535, in _startBuildFor
            d = build.startBuild(bs, self.expectations, slavebuilder)
        --- <exception caught here> ---
          File "/usr/local/lib/python2.6/dist-packages/buildbot-0.8.5-py2.6.egg/buildbot/process/build.py", line 233, in startBuild
            self.setupBuild(expectations) # create .steps
          File "/usr/local/lib/python2.6/dist-packages/buildbot-0.8.5-py2.6.egg/buildbot/process/build.py", line 288, in setupBuild
            step = factory(**args)
          File "/mnt/svn/buildbot/chem1dbbconfig/buildsteps.py", line 81, in __init__
            kwargs['workdir'] = 'build/test/case%s' % (str(self.testNumber))
        exceptions.AttributeError: Chem1dTest instance has no attribute 'testNumber'

2012-02-20 12:25:19+0100 [-] releaseLocks(<Chem1dBuildSlave 'tfe208.wtb.tue.nl', current builders: chem1d documentation,chem1d linux-x86_64 nightly build>): []
Line 81 in __init__ komt hier overeen met line 40 in het stukje code dat ik heb gepost.

Zoals je kunt zien worden self.prog en self.separator wel goed opgeslagen, maar self.testNumber niet. Ik snap niet meer waar het nu fout gaat. Kan iemand mij helpen?

Luctor et Emergo || specs


Acties:
  • 0 Henk 'm!

  • Juup
  • Registratie: Februari 2000
  • Niet online
tl;dr

Komt het misschien omdat je op regel 65 dit doet:
Python:
1
2
3
 testSteps.append(Chem1dTest(
        prog='trot', system=system
    ))

?

Man has 2 testicles but only 1 heart...


Acties:
  • 0 Henk 'm!

  • DutchNutcase
  • Registratie: Augustus 2005
  • Niet online
Nee, dat geeft geen problemen (voor zover ik kan zien), omdat make_tests maar een keer aangeroepen wordt en dan gaat alles goed.

Luctor et Emergo || specs


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:12
Uit de logfile blijkt dat Buildbot je testklasse aanroept zonder de door jou gewenste argumenten, dus dan is het logisch dat testNumber leeg is. De vraag is dus eigenlijk: waarom roept Buildbot direct de constructor aan in plaats van make_tests() aan te roepen om een lijst met tests te krijgen?

Welke klasse is die superklasse "Test" waar Chem1dTest op gebaseerd is precies? Misschien zijn er meer methoden die moet overschrijven dan alleen de constructor (bijvoorbeeld factory methods of annotaties voor serialisatie).

[ Voor 16% gewijzigd door Soultaker op 20-02-2012 20:01 ]


Acties:
  • 0 Henk 'm!

  • DutchNutcase
  • Registratie: Augustus 2005
  • Niet online
Soultaker schreef op maandag 20 februari 2012 @ 20:00:
Uit de logfile blijkt dat Buildbot je testklasse aanroept zonder de door jou gewenste argumenten, dus dan is het logisch dat testNumber leeg is. De vraag is dus eigenlijk: waarom roept Buildbot direct de constructor aan in plaats van make_tests() aan te roepen om een lijst met tests te krijgen?

Welke klasse is die superklasse "Test" waar Chem1dTest op gebaseerd is precies? Misschien zijn er meer methoden die moet overschrijven dan alleen de constructor (bijvoorbeeld factory methods of annotaties voor serialisatie).
Die superklasse Test is de klasse Test uit buildsteps.py van de buildbot master. Het gekke is dat self.prog wel geset is, maar self.testNumber niet. Dat de constructor aangeroepen word zonder argumenten is niet zo gek, maar dat slechts één van de te onthouden attributes leeg is wel.

Je hebt overigens helemaal gelijk: waarom word de constuctor hier nogmaals aangeroepen? Ik ga eens even in de buildbot source code kijken wat hier gebeurd.

edit:
Uiteindelijk is het opgelost door de class aan te passen naar:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Chem1dTest(Test):
    prog = None
    testNumber = None

    def __init__(self, prog=None, system=None, testNumber=None, **kwargs):
        if prog:
            self.prog = prog
        else:
            self.prog = 'chem1d'
        if system:
            if 'win' in system:
                separator = '\\'
            else:
                separator = '/'
        else:
            separator = '/'
        if testNumber:
            self.testNumber = testNumber

        if self.prog == 'chem1d':
            kwargs['command'] = ['..%s..%sbin%schem1d' % (separator, separator, separator)]
            kwargs['workdir'] = 'build/test/case%s' % (str(self.testNumber))
            kwargs['description'] = ['Running', 'test', 'case', str(self.testNumber)]
            kwargs['descriptionDone'] = ['Test', str(self.testNumber)]
        elif self.prog == 'trot':
            kwargs['command'] = ['..%s..%sbin%strot' % (separator, separator, separator)]
            kwargs['workdir'] = 'build/test/trot'
            kwargs['description'] = ['Running', 'trot', 'integration', 'test']
            kwargs['descriptionDone'] = ['Trot', 'test']

        Test.__init__(self, **kwargs)

        self.addFactoryArguments(prog=self.prog,
                                 system=system,
                                 testNumber=self.testNumber)

[ Voor 40% gewijzigd door DutchNutcase op 21-02-2012 13:23 . Reden: opgelost ]

Luctor et Emergo || specs


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:12
DutchNutcase schreef op dinsdag 21 februari 2012 @ 07:53:
Die superklasse Test is de klasse Test uit buildsteps.py van de buildbot master. Het gekke is dat self.prog wel geset is, maar self.testNumber niet.
Dát lijkt me nou juist niet gek, want die stel je zelf in op regel 8.
Uiteindelijk is het opgelost door de class aan te passen naar: [..]
Hmm ok, het zal wel. :p

Acties:
  • 0 Henk 'm!

  • DutchNutcase
  • Registratie: Augustus 2005
  • Niet online
Soultaker schreef op woensdag 22 februari 2012 @ 01:52:
[...]

Dát lijkt me nou juist niet gek, want die stel je zelf in op regel 8.
Ja, natuurlijk. |:( Oeps...

Blijkbaar heeft Buildbot een geabstraheerde manier om de builds te maken. Deze worden dynamisch iedere keer aangemaakt ipv in het geheugen gehouden. De methode addFactoryArguments zorgt dan dat de klasse met de juiste argumenten aangemaakt wordt.

Zo leer je iedere dag wat.

Luctor et Emergo || specs

Pagina: 1