aboutsummaryrefslogtreecommitdiffstats
path: root/meta/classes/update-rc.d.bbclass
blob: 5d67a485e9ab97b611390c14103daa3f240ee6ef (plain)
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
UPDATERCPN ?= "${PN}"

DEPENDS_append = " update-rc.d-native"
VIRTUAL-RUNTIME_initscripts ?= "initscripts"
DEPENDS_append_class-target = " ${VIRTUAL-RUNTIME_initscripts}"
UPDATERCD = "update-rc.d"
UPDATERCD_class-cross = ""
UPDATERCD_class-native = ""
UPDATERCD_class-nativesdk = ""

INITSCRIPT_PARAMS ?= "defaults"

INIT_D_DIR = "${sysconfdir}/init.d"

updatercd_preinst() {
if [ -z "$D" -a -f "${INIT_D_DIR}/${INITSCRIPT_NAME}" ]; then
	${INIT_D_DIR}/${INITSCRIPT_NAME} stop
fi
if type update-rc.d >/dev/null 2>/dev/null; then
	if [ -n "$D" ]; then
		OPT="-f -r $D"
	else
		OPT="-f"
	fi
	update-rc.d $OPT ${INITSCRIPT_NAME} remove
fi
}

updatercd_postinst() {
if type update-rc.d >/dev/null 2>/dev/null; then
	if [ -n "$D" ]; then
		OPT="-r $D"
	else
		OPT="-s"
	fi
	update-rc.d $OPT ${INITSCRIPT_NAME} ${INITSCRIPT_PARAMS}
fi
}

updatercd_prerm() {
if [ -z "$D" ]; then
	${INIT_D_DIR}/${INITSCRIPT_NAME} stop
fi
}

updatercd_postrm() {
if type update-rc.d >/dev/null 2>/dev/null; then
	if [ -n "$D" ]; then
		OPT="-f -r $D"
	else
		OPT="-f"
	fi
	update-rc.d $OPT ${INITSCRIPT_NAME} remove
fi
}


def update_rc_after_parse(d):
    if d.getVar('INITSCRIPT_PACKAGES', False) == None:
        if d.getVar('INITSCRIPT_NAME', False) == None:
            raise bb.build.FuncFailed("%s inherits update-rc.d but doesn't set INITSCRIPT_NAME" % d.getVar('FILE', False))
        if d.getVar('INITSCRIPT_PARAMS', False) == None:
            raise bb.build.FuncFailed("%s inherits update-rc.d but doesn't set INITSCRIPT_PARAMS" % d.getVar('FILE', False))

python __anonymous() {
    update_rc_after_parse(d)
}

PACKAGESPLITFUNCS_prepend = "populate_packages_updatercd "
PACKAGESPLITFUNCS_remove_class-nativesdk = "populate_packages_updatercd "

populate_packages_updatercd[vardeps] += "updatercd_prerm updatercd_postrm updatercd_preinst updatercd_postinst"
populate_packages_updatercd[vardepsexclude] += "OVERRIDES"

python populate_packages_updatercd () {
    def update_rcd_auto_depend(pkg):
        import subprocess
        import os
        path = d.expand("${D}${INIT_D_DIR}/${INITSCRIPT_NAME}")
        if not os.path.exists(path):
            return
        statement = "grep -q -w '/etc/init.d/functions' %s" % path
        if subprocess.call(statement, shell=True) == 0:
            mlprefix = d.getVar('MLPREFIX', True) or ""
            d.appendVar('RDEPENDS_' + pkg, ' %sinitscripts-functions' % (mlprefix))

    def update_rcd_package(pkg):
        bb.debug(1, 'adding update-rc.d calls to preinst/postinst/prerm/postrm for %s' % pkg)

        localdata = bb.data.createCopy(d)
        overrides = localdata.getVar("OVERRIDES", True)
        localdata.setVar("OVERRIDES", "%s:%s" % (pkg, overrides))
        bb.data.update_data(localdata)

        update_rcd_auto_depend(pkg)

        preinst = d.getVar('pkg_preinst_%s' % pkg, True)
        if not preinst:
            preinst = '#!/bin/sh\n'
        preinst += localdata.getVar('updatercd_preinst', True)
        d.setVar('pkg_preinst_%s' % pkg, preinst)

        postinst = d.getVar('pkg_postinst_%s' % pkg, True)
        if not postinst:
            postinst = '#!/bin/sh\n'
        postinst += localdata.getVar('updatercd_postinst', True)
        d.setVar('pkg_postinst_%s' % pkg, postinst)

        prerm = d.getVar('pkg_prerm_%s' % pkg, True)
        if not prerm:
            prerm = '#!/bin/sh\n'
        prerm += localdata.getVar('updatercd_prerm', True)
        d.setVar('pkg_prerm_%s' % pkg, prerm)

        postrm = d.getVar('pkg_postrm_%s' % pkg, True)
        if not postrm:
                postrm = '#!/bin/sh\n'
        postrm += localdata.getVar('updatercd_postrm', True)
        d.setVar('pkg_postrm_%s' % pkg, postrm)

        d.appendVar('RRECOMMENDS_' + pkg, " ${MLPREFIX}${UPDATERCD}")

    # Check that this class isn't being inhibited (generally, by
    # systemd.bbclass) before doing any work.
    if bb.utils.contains('DISTRO_FEATURES', 'sysvinit', True, False, d) or \
       not d.getVar("INHIBIT_UPDATERCD_BBCLASS", True):
        pkgs = d.getVar('INITSCRIPT_PACKAGES', True)
        if pkgs == None:
            pkgs = d.getVar('UPDATERCPN', True)
            packages = (d.getVar('PACKAGES', True) or "").split()
            if not pkgs in packages and packages != []:
                pkgs = packages[0]
        for pkg in pkgs.split():
            update_rcd_package(pkg)
}
span> Simple usage example: class Credentials(namedtuple.abc): _fields = 'username password' def __str__(self): return ('{0.__class__.__name__}' '(username={0.username}, password=...)'.format(self)) print(Credentials("alice", "Alice's password")) For more advanced examples -- see below the "if __name__ == '__main__':". """ import collections from abc import ABCMeta, abstractproperty from functools import wraps from sys import version_info __all__ = ('namedtuple',) _namedtuple = collections.namedtuple class _NamedTupleABCMeta(ABCMeta): '''The metaclass for the abstract base class + mix-in for named tuples.''' def __new__(mcls, name, bases, namespace): fields = namespace.get('_fields') for base in bases: if fields is not None: break fields = getattr(base, '_fields', None) if not isinstance(fields, abstractproperty): basetuple = _namedtuple(name, fields) bases = (basetuple,) + bases namespace.pop('_fields', None) namespace.setdefault('__doc__', basetuple.__doc__) namespace.setdefault('__slots__', ()) return ABCMeta.__new__(mcls, name, bases, namespace) exec( # Python 2.x metaclass declaration syntax """class _NamedTupleABC(object): '''The abstract base class + mix-in for named tuples.''' __metaclass__ = _NamedTupleABCMeta _fields = abstractproperty()""" if version_info[0] < 3 else # Python 3.x metaclass declaration syntax """class _NamedTupleABC(metaclass=_NamedTupleABCMeta): '''The abstract base class + mix-in for named tuples.''' _fields = abstractproperty()""" ) _namedtuple.abc = _NamedTupleABC #_NamedTupleABC.register(type(version_info)) # (and similar, in the future...) @wraps(_namedtuple) def namedtuple(*args, **kwargs): '''Named tuple factory with namedtuple.abc subclass registration.''' cls = _namedtuple(*args, **kwargs) _NamedTupleABC.register(cls) return cls collections.namedtuple = namedtuple if __name__ == '__main__': '''Examples and explanations''' # Simple usage class MyRecord(namedtuple.abc): _fields = 'x y z' # such form will be transformed into ('x', 'y', 'z') def _my_custom_method(self): return list(self._asdict().items()) # (the '_fields' attribute belongs to the named tuple public API anyway) rec = MyRecord(1, 2, 3) print(rec) print(rec._my_custom_method()) print(rec._replace(y=222)) print(rec._replace(y=222)._my_custom_method()) # Custom abstract classes... class MyAbstractRecord(namedtuple.abc): def _my_custom_method(self): return list(self._asdict().items()) try: MyAbstractRecord() # (abstract classes cannot be instantiated) except TypeError as exc: print(exc) class AnotherAbstractRecord(MyAbstractRecord): def __str__(self): return '<<<{0}>>>'.format(super(AnotherAbstractRecord, self).__str__()) # ...and their non-abstract subclasses class MyRecord2(MyAbstractRecord): _fields = 'a, b' class MyRecord3(AnotherAbstractRecord): _fields = 'p', 'q', 'r' rec2 = MyRecord2('foo', 'bar') print(rec2) print(rec2._my_custom_method()) print(rec2._replace(b=222)) print(rec2._replace(b=222)._my_custom_method()) rec3 = MyRecord3('foo', 'bar', 'baz') print(rec3) print(rec3._my_custom_method()) print(rec3._replace(q=222)) print(rec3._replace(q=222)._my_custom_method()) # You can also subclass non-abstract ones... class MyRecord33(MyRecord3): def __str__(self): return '< {0!r}, ..., {0!r} >'.format(self.p, self.r) rec33 = MyRecord33('foo', 'bar', 'baz') print(rec33) print(rec33._my_custom_method()) print(rec33._replace(q=222)) print(rec33._replace(q=222)._my_custom_method()) # ...and even override the magic '_fields' attribute again class MyRecord345(MyRecord3): _fields = 'e f g h i j k' rec345 = MyRecord345(1, 2, 3, 4, 3, 2, 1) print(rec345) print(rec345._my_custom_method()) print(rec345._replace(f=222)) print(rec345._replace(f=222)._my_custom_method()) # Mixing-in some other classes is also possible: class MyMixIn(object): def method(self): return "MyMixIn.method() called" def _my_custom_method(self): return "MyMixIn._my_custom_method() called" def count(self, item): return "MyMixIn.count({0}) called".format(item) def _asdict(self): # (cannot override a namedtuple method, see below) return "MyMixIn._asdict() called" class MyRecord4(MyRecord33, MyMixIn): # mix-in on the right _fields = 'j k l x' class MyRecord5(MyMixIn, MyRecord33): # mix-in on the left _fields = 'j k l x y' rec4 = MyRecord4(1, 2, 3, 2) print(rec4) print(rec4.method()) print(rec4._my_custom_method()) # MyRecord33's print(rec4.count(2)) # tuple's print(rec4._replace(k=222)) print(rec4._replace(k=222).method()) print(rec4._replace(k=222)._my_custom_method()) # MyRecord33's print(rec4._replace(k=222).count(8)) # tuple's rec5 = MyRecord5(1, 2, 3, 2, 1) print(rec5) print(rec5.method()) print(rec5._my_custom_method()) # MyMixIn's print(rec5.count(2)) # MyMixIn's print(rec5._replace(k=222)) print(rec5._replace(k=222).method()) print(rec5._replace(k=222)._my_custom_method()) # MyMixIn's print(rec5._replace(k=222).count(2)) # MyMixIn's # None that behavior: the standard namedtuple methods cannot be # overriden by a foreign mix-in -- even if the mix-in is declared # as the leftmost base class (but, obviously, you can override them # in the defined class or its subclasses): print(rec4._asdict()) # (returns a dict, not "MyMixIn._asdict() called") print(rec5._asdict()) # (returns a dict, not "MyMixIn._asdict() called") class MyRecord6(MyRecord33): _fields = 'j k l x y z' def _asdict(self): return "MyRecord6._asdict() called" rec6 = MyRecord6(1, 2, 3, 1, 2, 3) print(rec6._asdict()) # (this returns "MyRecord6._asdict() called") # All that record classes are real subclasses of namedtuple.abc: assert issubclass(MyRecord, namedtuple.abc) assert issubclass(MyAbstractRecord, namedtuple.abc) assert issubclass(AnotherAbstractRecord, namedtuple.abc) assert issubclass(MyRecord2, namedtuple.abc) assert issubclass(MyRecord3, namedtuple.abc) assert issubclass(MyRecord33, namedtuple.abc) assert issubclass(MyRecord345, namedtuple.abc) assert issubclass(MyRecord4, namedtuple.abc) assert issubclass(MyRecord5, namedtuple.abc) assert issubclass(MyRecord6, namedtuple.abc) # ...but abstract ones are not subclasses of tuple # (and this is what you probably want): assert not issubclass(MyAbstractRecord, tuple) assert not issubclass(AnotherAbstractRecord, tuple) assert issubclass(MyRecord, tuple) assert issubclass(MyRecord2, tuple) assert issubclass(MyRecord3, tuple) assert issubclass(MyRecord33, tuple) assert issubclass(MyRecord345, tuple) assert issubclass(MyRecord4, tuple) assert issubclass(MyRecord5, tuple) assert issubclass(MyRecord6, tuple) # Named tuple classes created with namedtuple() factory function # (in the "traditional" way) are registered as "virtual" subclasses # of namedtuple.abc: MyTuple = namedtuple('MyTuple', 'a b c') mt = MyTuple(1, 2, 3) assert issubclass(MyTuple, namedtuple.abc) assert isinstance(mt, namedtuple.abc)