1#!/usr/bin/env python3
2#
3#  Copyright (c) 2019, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28#
29
30nullField = None
31
32
33class NullField(object):
34    """
35    Represents a null field that does not exists.
36    """
37
38    def __new__(cls, *args, **kwargs):
39        global nullField
40
41        if nullField is None:
42            nullField = object.__new__(cls, *args, **kwargs)
43
44        return nullField
45
46    def __init__(self):
47        assert self is nullField
48
49    def __bool__(self):
50        """
51        NullField is always treated as False.
52        """
53        return False
54
55    def __getattr__(self, item):
56        """
57        Any sub field of the NullField is NullField itself.
58        """
59        return self
60
61    def __setattr__(self, key, value):
62        pass
63
64    def __len__(self) -> 0:
65        return 0
66
67    def __eq__(self, other):
68        """
69        NullField is always not equal to any other value.
70        """
71        return False
72
73    def __ne__(self, other):
74        return True
75
76    def __lt__(self, other):
77        """
78        Comparing NullField to any other value gets False.
79        """
80        return False
81
82    def __le__(self, other):
83        """
84        Comparing NullField to any other value gets False.
85        """
86        return False
87
88    def __gt__(self, other):
89        """
90        Comparing NullField to any other value gets False.
91        """
92        return False
93
94    def __ge__(self, other):
95        """
96        Comparing NullField to any other value gets False.
97        """
98        return False
99
100    def __str__(self):
101        return "nullField"
102
103    def __repr__(self):
104        return 'nullField'
105
106
107NullField()
108
109if __name__ == '__main__':
110    assert nullField is NullField()
111    assert not nullField, repr(nullField)
112    assert nullField != nullField, repr(nullField)
113    assert nullField != 0
114    assert not (nullField > 1)
115    assert not (nullField < 1)
116    assert not (nullField < nullField)
117    assert not (nullField > nullField)
118    assert bool(nullField) is False
119    assert nullField != ""
120    assert nullField != None  # noqa
121    assert nullField is not None
122