pandas-dev/pandas · error · NotImplementedError

Unary addition not supported

Error message

Unary addition not supported

What it means

Raised in PyTablesExprVisitor.visit_UnaryOp when node.op is an ast.UAdd — i.e. a unary plus such as '+A'. The visitor handles ast.Not/ast.Invert (mapped to '~'), and ast.USub (folded into a negated Constant), but unary addition has no meaningful effect on a filter condition and is explicitly unsupported, so it raises NotImplementedError.

Solutions

  1. Remove the unary '+' from the predicate: store.select('df', where='A > 0').
  2. If the '+' comes from a code generator, strip leading '+' tokens before passing the where string.
  3. Filter in pandas: df = store.get('df'); df[df['A'] > 0].

Example fix

// before
store.select('df', where='+A > 0')

// after
store.select('df', where='A > 0')
Defensive patterns

Strategy: validation

Validate before calling

import re

def where_has_unary_plus(where: str) -> bool:
    return bool(re.search(r'(?<![\w\d)])\+[A-Za-z_(]', where))

assert not where_has_unary_plus(where_clause), 'unary + is not supported in HDFStore where clauses'

Type guard

def is_supported_unary_node(op_node) -> bool:
    import ast
    return isinstance(op_node, (ast.Not, ast.Invert, ast.USub))

Try / catch

try:
    store.select('df', where='+A > 0')
except NotImplementedError as e:
    if 'Unary addition not supported' in str(e):
        store.select('df', where='A > 0')
    else:
        raise

Prevention

When it happens

Trigger: store.select('df', where='+A > 0'), store.select('df', where='+(+A) > 0'), or any where clause containing a unary '+' prefix on an operand.

Common situations: Copy-pasting an expression that used unary '+' for emphasis (e.g. SQL port). Auto-generated predicates that prepend '+' to numeric columns. Code generators that emit UAdd nodes unconditionally.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/5d2e719948179002. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/computation/pytables.py:466

    term_type: ClassVar[type[Term]] = Term

    def __init__(self, env, engine, parser, **kwargs) -> None:
        super().__init__(env, engine, parser)
        for bin_op in self.binary_ops:
            bin_node = self.binary_op_nodes_map[bin_op]
            setattr(
                self,
                f"visit_{bin_node}",
                lambda node, bin_op=bin_op: partial(BinOp, bin_op, **kwargs),
            )

    def visit_UnaryOp(self, node, **kwargs) -> ops.Term | UnaryOp | None:
        if isinstance(node.op, (ast.Not, ast.Invert)):
            return UnaryOp("~", self.visit(node.operand))
        elif isinstance(node.op, ast.USub):
            return self.const_type(-self.visit(node.operand).value, self.env)
        elif isinstance(node.op, ast.UAdd):
            raise NotImplementedError("Unary addition not supported")
        # TODO: return None might never be reached
        return None

    def visit_Index(self, node, **kwargs):
        return self.visit(node.value).value

    def visit_Assign(self, node, **kwargs):
        cmpr = ast.Compare(
            ops=[ast.Eq()], left=node.targets[0], comparators=[node.value]
        )
        return self.visit(cmpr)

    def visit_Subscript(self, node, **kwargs) -> ops.Term:
        # only allow simple subscripts

        value = self.visit(node.value)
        slobj = self.visit(node.slice)
        try:

View on GitHub (pinned to 3b7651241d)