1 """
2 Framework for ignoring rows based on various conditions.
3 """
4
5
6
7
8
9
10
11 from gavo import base
12 from gavo.base import typesystems
13
14
17 base.Error.__init__(self, msg)
18 self.triggerName = triggerName
19 self.args = [msg, triggerName]
20
21
22 _triggerRegistry = {}
26
29
30
32 """A trigger, i.e., a boolean construct.
33
34 This element does not actually occur in resource descriptors.
35 Refer to Triggers_ for triggers actually available.
36 """
37
38
39
40 name_ = "trigger"
41
42 _name = base.UnicodeAttribute("name", default="unnamed",
43 description="A name that should help the user figure out what trigger"
44 " caused some condition to fire.", copyable=True)
45
46
52
53
55 """A trigger firing if a certain key is present in the dict.
56 """
57 name_ = "keyPresent"
58
60 return self.key in dict
61
62 registerTrigger(KeyPresent)
63
64
66 """A trigger firing if a certain key is missing in the dict.
67
68 This is equivalent to::
69
70 <not><keyPresent key="xy"/></not>
71 """
72 name_ = "keyMissing"
73
75 return self.key not in dict
76
77 registerTrigger(KeyMissing)
78
79
81 """A trigger firing if a certain key is missing or NULL/None
82 """
83 name_ = "keyNull"
84
86 return dict.get(self.key) is None
87
88 registerTrigger(KeyNull)
89
90
91
92 -class KeyIs(KeyedCondition):
93 """A trigger firing when the value of key in row is equal to the value given.
94
95 Missing keys are always accepted. You can define an SQL type; value will
96 then be interpreted as a literal for this type, and this literal's value will
97 be compared against the key's value. This is only needed for grammars like
98 fitsProductGrammar that actually yield typed values.
99 """
100 name_ = "keyIs"
101
102 _value = base.UnicodeAttribute("value", default=base.Undefined,
103 description="The string value to fire on.", copyable=True)
104 _type = base.UnicodeAttribute("type", default="text",
105 description="An SQL type the python equivalent of which the value"
106 " should be converted to before checking.")
107
112
114 return self.key in dict and dict[self.key]==self.compValue
115
116 registerTrigger(KeyIs)
117
118
120 """is an abstract base for anything that can incorporate the
121 basic triggers.
122
123 If you don't override __call__, the basic operation is or-ing together
124 all embedded conditions.
125 """
126 _triggers = base.MultiStructListAttribute("triggers",
127 childFactory=getTrigger, childNames=_triggerRegistry,
128 description=("One or more conditions joined by an implicit logical or."
129 " See Triggers_ for information on what can stand here."),
130 copyable=True)
131
133 for t in self.triggers:
134 if t(dict):
135 return True
136 return False
137
138
139 -class Not(ConditionBase):
140 """A trigger that is false when its children, or-ed together, are true and
141 vice versa.
142 """
143 name_ = "not"
144
147
148 registerTrigger(Not)
149
150
151 -class And(ConditionBase):
152 """A trigger that is true when all its children are true.
153 """
154 name_ = "and"
155
157 for t in self.triggers:
158 if not t(dict):
159 return False
160 return True
161
162 registerTrigger(And)
163
164
166 """A condition on a row that, if true, causes the row to be dropped.
167
168 Here, you can set bail to abort an import when the condition is met
169 rather than just dropping the row.
170 """
171 name_ = "ignoreOn"
172 _bail = base.BooleanAttribute("bail", default=False, description=
173 "Abort when condition is met?")
174
181