{"record":{"id":"6b4d1a0dafbc4c64","repo":"pandas-dev/pandas","slug":"unaryop-only-support-invert-type-ops","errorCode":null,"errorMessage":"UnaryOp only support invert type ops","messagePattern":"UnaryOp only support invert type ops","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/pytables.py","lineNumber":429,"sourceCode":"            else:\n                return None\n        else:\n            self.condition = self.generate(values[0])\n\n        return self\n\n\nclass JointConditionBinOp(ConditionBinOp):\n    # error: Signature of \"evaluate\" incompatible with supertype \"BinOp\"\n    def evaluate(self) -> Self:  # type: ignore[override]\n        self.condition = f\"({self.lhs.condition} {self.op} {self.rhs.condition})\"\n        return self\n\n\nclass UnaryOp(ops.UnaryOp):\n    def prune(self, klass):\n        if self.op != \"~\":\n            raise NotImplementedError(\"UnaryOp only support invert type ops\")\n\n        operand = self.operand\n        operand = operand.prune(klass)\n\n        if operand is not None and (\n            (issubclass(klass, ConditionBinOp) and operand.condition is not None)\n            or (\n                not issubclass(klass, ConditionBinOp)\n                and issubclass(klass, FilterBinOp)\n                and operand.filter is not None\n            )\n        ):\n            return operand.invert()\n        return None\n\n\nclass PyTablesExprVisitor(BaseExprVisitor):\n    const_type: ClassVar[type[ops.Term]] = Constant","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/computation/pytables.py#L411-L447","documentation":"Raised by UnaryOp.prune in pandas.core.computation.pytables when the unary operator is not '~'. The pytables visitor only supports invert ('~' / 'not') as a unary op in where clauses; '+' and '-' are handled earlier in visit_UnaryOp (USub becomes a negated constant, UAdd raises separately). If any other unary form reaches pruning, this NotImplementedError fires.","triggerScenarios":"Constructing a pytables UnaryOp directly with op in ('+','-','not' but mistyped), or a custom AST path that yields a non-invert unary in a where clause. In normal where strings, '+' and '-' are intercepted before prune, so this is largely defensive.","commonSituations":"Custom subclasses of the pytables visitor; experimental AST manipulation; using 'not' in a context that bypasses visit_UnaryOp's remap.","solutions":["Use only '~' (or 'not') for unary negation in where clauses: where='~(a > 0)'.","For arithmetic negation, precompute the column (df['neg_a'] = -df['a']) and store as a data_column, then query that.","Avoid constructing UnaryOp manually; rely on the parser via PyTablesExpr/where strings."],"exampleFix":"# before\nstore.select('df', where='-a > 0')  # may raise UnaryOp only support invert type ops after remap\n\n# after (precompute)\ndf['neg_a'] = -df['a']\nstore.put('df', df, format='table', data_columns=['neg_a'])\nstore.select('df', where='neg_a > 0')","handlingStrategy":"validation","validationCode":"def assert_invert_only_unary(op: str) -> str:\n    if op != '~':\n        raise NotImplementedError(f'pytables UnaryOp only supports ~, got {op!r}')\n    return op","typeGuard":"def is_invert_unary(op: str) -> bool:\n    return op == '~'","tryCatchPattern":"try:\n    store.select('df', where=where)\nexcept NotImplementedError as e:\n    if 'UnaryOp only support invert' in str(e):\n        df = store.get('df')\n        result = df.query(where)\n    else:\n        raise","preventionTips":["Use only '~' (or 'not') for unary negation in pytables where clauses.","Precompute negated columns as data_columns when arithmetic negation is needed.","Avoid constructing pytables UnaryOp manually."],"tags":["pandas","hdf5","pytables","where","unary"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}