2.2 Core model

2.2.1 Core settings

Baelfire use MorfDict‘s StringDict for settings and PathDict for path configuration. All linked tasks have the same settings and paths object, so we can edit in the parent task if we want, but this is not recomended. Better way is to make all the configuration in the Core object.

doc4.py
 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
from baelfire.core import Core
from baelfire.dependencies import AlwaysTrue
from baelfire.dependencies import TaskRebuilded
from baelfire.task import Task


class MyCore(Core):

    def phase_settings(self):
        super(MyCore, self).phase_settings()
        self.settings['first'] = 'my %(parent)s'
        self.settings['parent'] = 'me'
        self.paths.set('first', 'first.txt', parent='base')


class FirstTask(Task):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        print('S', self.settings['first'])
        self.paths.set('base', 'base', is_root=True)
        print('S', self.paths.get('first'))


class ParentTask(Task):

    def create_dependecies(self):
        self.build_if(TaskRebuilded(FirstTask()))

    def build(self):
        self.settings['parent'] = 'parent'
        print('P', self.settings['first'])
        print('P', self.paths.get('first'))

if __name__ == '__main__':
    ParentTask(MyCore()).run()
$ python doc4.py
S my parent
S /base/first.txt
P my parent
P /base/first.txt

We create 2 tasks and make settings for both of them. From Parent task we can ovveride some settings within a child tasks.

2.2.2 Saving and loading settings

Sometimes we would like to save settings, so it can be retrived from disk. For example, the name of the project we need only at the start and we can retrive it from disk next time, but the rest of the configuration can be stored in python code.

doc11.py
 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
from baelfire.core import Core
from baelfire.dependencies import AlwaysTrue
from baelfire.filedict import FileDict
from baelfire.task import Task


class MyCore(Core):

    def phase_settings(self):
        super(MyCore, self).phase_settings()
        data = FileDict('.file.yaml')
        data.load(True)
        data.ensure_key_exists('something', 'Description for something')
        data.save()

        self.settings['something'] = data['something']


class MyTask(Task):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        print(self.settings['something'])


if __name__ == '__main__':
    MyTask(MyCore()).run()
$ python doc11.py
Description for something: testme
testme
$ python doc11.py
testme
$

2.2.3 Task replacment

Warning

This feature can result in very unreadable code. Use with caution! Use only as a last resort!

Creating task hierarchy can be very tricky. Sometimes we would like to change small thing in a task, but do not change the rest of the hierarchy. Core object can replace one task class with another. In the next example we will have 3 tasks depending on each other: TaskA, TaskB, TaskC. And then we will replace TaskB with TaskD.

Before:

Before change

After:

After change
doc13.py
 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
from baelfire.core import Core
from baelfire.dependencies import AlwaysTrue
from baelfire.dependencies import TaskRebuilded
from baelfire.task import Task


class MyCore(Core):

    def make_task_inheritance(self):
        super(MyCore, self).make_task_inheritance()
        self.add_task_inheritance(TaskB, TaskD, self._migration)

    def _migration(self, left, right):
        print(left, right)
        return right()


class TaskA(Task):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        print('I am task A')


class TaskB(Task):

    def create_dependecies(self):
        self.build_if(TaskRebuilded(TaskA()))

    def build(self):
        print('I am task B')


class TaskC(Task):

    def create_dependecies(self):
        self.build_if(TaskRebuilded(TaskB()))

    def build(self):
        print('I am task C')


class TaskD(Task):

    def create_dependecies(self):
        self.build_if(TaskRebuilded(TaskA()))

    def build(self):
        print('I am task D')


if __name__ == '__main__':
    TaskC().run()
    print('-------------')
    TaskC(MyCore()).run()
$ python doc13.py
I am task A
I am task B
I am task C
-------------
I am task A
I am task D
I am task C

2.2.4 Task replacment - migration

You can also make a migration script. If you would like to change something, or just to make more debug, like in the example.

doc14.py
 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
from baelfire.core import Core
from baelfire.dependencies import AlwaysTrue
from baelfire.dependencies import TaskRebuilded
from baelfire.task import Task


class MyCore(Core):

    def make_task_inheritance(self):
        super(MyCore, self).make_task_inheritance()
        self.add_task_inheritance(TaskA, TaskC, self._migration)

    def _migration(self, left, right):
        print(left, right)
        return right()


class TaskA(Task):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        print('I am task A')


class TaskB(Task):

    def create_dependecies(self):
        self.build_if(TaskRebuilded(TaskA()))

    def build(self):
        print('I am task B')


class TaskC(Task):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        print('I am task C')


if __name__ == '__main__':
    TaskB(MyCore()).run()
$ python doc14.py
<__main__.TaskA object at 0x7f23af21bbe0> <class '__main__.TaskC'>
I am task C
I am task B