@@ -140,6 +140,9 @@ def __and__(self, other):
140
140
def __xor__ (self , other ):
141
141
return XOrCategory (self , other )
142
142
143
+ def __invert__ (self ):
144
+ return NotCategory (self )
145
+
143
146
144
147
@set_module ("sisl.category" )
145
148
class NullCategory (Category ):
@@ -167,6 +170,46 @@ def name(self):
167
170
return "∅"
168
171
169
172
173
+ @set_module ("sisl.category" )
174
+ class NotCategory (Category ):
175
+ """ A class returning the *opposite* of this class (NullCategory) if it is categorized as such """
176
+ __slots__ = ("_cat" ,)
177
+
178
+ def __init__ (self , cat ):
179
+ super ().__init__ ()
180
+ if isinstance (cat , CompositeCategory ):
181
+ self .set_name (f"~({ cat } )" )
182
+ else :
183
+ self .set_name (f"~{ cat } " )
184
+ self ._cat = cat
185
+
186
+ def categorize (self , * args , ** kwargs ):
187
+ r""" Base method for queriyng whether an object is a certain category """
188
+ cat = self ._cat .categorize (* args , ** kwargs )
189
+
190
+ def check (cat ):
191
+ if isinstance (cat , NullCategory ):
192
+ return self
193
+ return NullCategory ()
194
+
195
+ if isinstance (cat , list ):
196
+ return list (map (check , cat ))
197
+ return check (cat )
198
+
199
+ @singledispatchmethod
200
+ def __eq__ (self , other ):
201
+ if isinstance (other , NotCategory ):
202
+ return self ._cat == other ._cat
203
+ return False
204
+
205
+ @__eq__ .register (list )
206
+ @__eq__ .register (tuple )
207
+ @__eq__ .register (np .ndarray )
208
+ def _ (self , other ):
209
+ # this will call the list approach
210
+ return super ().__eq__ (other )
211
+
212
+
170
213
@set_module ("sisl.category" )
171
214
class CompositeCategory (Category ):
172
215
""" A composite class consisting of two categories
0 commit comments