diff --git a/claripy/ast/base.py b/claripy/ast/base.py index a6536013b..5a44b4909 100644 --- a/claripy/ast/base.py +++ b/claripy/ast/base.py @@ -5,8 +5,9 @@ import struct import weakref from collections import OrderedDict, deque +from collections.abc import Iterable, Iterator from itertools import chain -from typing import TYPE_CHECKING, Generic, Iterable, Iterator, List, NoReturn, Optional, Tuple, TypeVar +from typing import TYPE_CHECKING, Generic, NoReturn, TypeVar from claripy import operations, simplifications from claripy.backend_manager import backends @@ -376,7 +377,7 @@ def _calc_hash(op, args, keywords): return md5_unpacker.unpack(hd)[0] # 64 bits @staticmethod - def _arg_serialize(arg) -> Optional[bytes]: + def _arg_serialize(arg) -> bytes | None: if arg is None: return b"\x0f" elif arg is True: @@ -416,7 +417,7 @@ def _arg_serialize(arg) -> Optional[bytes]: return None @staticmethod - def _ast_serialize(op: str, args_tup, keywords) -> Optional[bytes]: + def _ast_serialize(op: str, args_tup, keywords) -> bytes | None: """ Serialize the AST and get a bytestring for hashing. @@ -479,7 +480,7 @@ def __a_init__( self.length = length self.variables = frozenset(variables) if type(variables) is not frozenset else variables self.symbolic = symbolic - self.annotations: Tuple[Annotation] = annotations + self.annotations: tuple[Annotation] = annotations self._uneliminatable_annotations = uneliminatable_annotations self._relocatable_annotations = relocatable_annotations @@ -610,7 +611,7 @@ def append_annotation(self: T, a: "Annotation") -> T: """ return self._apply_to_annotations(lambda alist: (*alist, a)) - def append_annotations(self: T, new_tuple: Tuple["Annotation", ...]) -> T: + def append_annotations(self: T, new_tuple: tuple["Annotation", ...]) -> T: """ Appends several annotations to this AST. @@ -619,7 +620,7 @@ def append_annotations(self: T, new_tuple: Tuple["Annotation", ...]) -> T: """ return self._apply_to_annotations(lambda alist: alist + new_tuple) - def annotate(self: T, *args: "Annotation", remove_annotations: Optional[Iterable["Annotation"]] = None) -> T: + def annotate(self: T, *args: "Annotation", remove_annotations: Iterable["Annotation"] | None = None) -> T: """ Appends annotations to this AST. @@ -643,7 +644,7 @@ def insert_annotation(self: T, a: "Annotation") -> T: """ return self._apply_to_annotations(lambda alist: (a, *alist)) - def insert_annotations(self: T, new_tuple: Tuple["Annotation", ...]) -> T: + def insert_annotations(self: T, new_tuple: tuple["Annotation", ...]) -> T: """ Inserts several annotations to this AST. @@ -652,7 +653,7 @@ def insert_annotations(self: T, new_tuple: Tuple["Annotation", ...]) -> T: """ return self._apply_to_annotations(lambda alist: new_tuple + alist) - def replace_annotations(self: T, new_tuple: Tuple["Annotation", ...]) -> T: + def replace_annotations(self: T, new_tuple: tuple["Annotation", ...]) -> T: """ Replaces annotations on this AST. @@ -893,7 +894,7 @@ def swap_args(self: T, new_args, new_length=None, **kwargs) -> T: # Other helper functions # - def split(self, split_on: Iterable[str]) -> List: + def split(self, split_on: Iterable[str]) -> list: """ Splits the AST if its operation is `split_on` (i.e., return all the arguments). Otherwise, return a list with just the AST. diff --git a/claripy/ast/strings.py b/claripy/ast/strings.py index f01af4001..b855faa4a 100644 --- a/claripy/ast/strings.py +++ b/claripy/ast/strings.py @@ -1,5 +1,3 @@ -from typing import Optional - from claripy import operations from claripy.ast.base import _make_name @@ -150,7 +148,7 @@ def StringS(name, size, uninitialized=False, explicit_name=False, **kwargs): return result -def StringV(value, length: Optional[int] = None, **kwargs): +def StringV(value, length: int | None = None, **kwargs): """ Create a new Concrete string (analogous to z3.StringVal()) diff --git a/claripy/backends/backend_concrete.py b/claripy/backends/backend_concrete.py index 1f8cf943b..c145109ca 100644 --- a/claripy/backends/backend_concrete.py +++ b/claripy/backends/backend_concrete.py @@ -139,7 +139,7 @@ def _identical(self, a, b): def _convert(self, a): if type(a) in {int, str, bytes}: return a - if isinstance(a, (numbers.Number, bv.BVV, fp.FPV, fp.RM, fp.FSort, strings.StringV)): + if isinstance(a, numbers.Number | bv.BVV | fp.FPV | fp.RM | fp.FSort | strings.StringV): return a raise BackendError(f"can't handle AST of type {type(a)}") @@ -168,9 +168,9 @@ def _cardinality(self, b): @staticmethod def _to_primitive(expr): - if isinstance(expr, (bv.BVV, fp.FPV, strings.StringV)): + if isinstance(expr, bv.BVV | fp.FPV | strings.StringV): return expr.value - elif isinstance(expr, (bool, numbers.Number)): + elif isinstance(expr, bool | numbers.Number): return expr else: raise BackendError("idk how to turn this into a primitive") diff --git a/claripy/backends/backend_vsa.py b/claripy/backends/backend_vsa.py index 00ec3a3a1..44ddfd1cf 100644 --- a/claripy/backends/backend_vsa.py +++ b/claripy/backends/backend_vsa.py @@ -134,7 +134,7 @@ def _convert(self, a): return a elif isinstance(a, bool): return TrueResult() if a else FalseResult() - if isinstance(a, (StridedInterval, DiscreteStridedIntervalSet, ValueSet)): + if isinstance(a, StridedInterval | DiscreteStridedIntervalSet | ValueSet): return a if isinstance(a, BoolResult): return a @@ -143,7 +143,7 @@ def _convert(self, a): raise BackendError def _eval(self, expr, n, extra_constraints=(), solver=None, model_callback=None): - if isinstance(expr, (StridedInterval, ValueSet)): + if isinstance(expr, StridedInterval | ValueSet): return expr.eval(n) elif isinstance(expr, BoolResult): return expr.value @@ -217,7 +217,7 @@ def _identical(self, a, b): return a.identical(b) def _unique(self, obj): # pylint:disable=unused-argument,no-self-use - if isinstance(obj, (StridedInterval, ValueSet)): + if isinstance(obj, StridedInterval | ValueSet): return obj.unique else: raise BackendError(f"Not supported type of operand {type(obj)}") diff --git a/claripy/backends/backend_z3.py b/claripy/backends/backend_z3.py index 5b61d638f..0c14b8d53 100644 --- a/claripy/backends/backend_z3.py +++ b/claripy/backends/backend_z3.py @@ -414,7 +414,7 @@ def _convert(self, obj): # pylint:disable=arguments-renamed return z3.BoolRef(z3.Z3_mk_true(self._context.ref()), self._context) elif obj is False: return z3.BoolRef(z3.Z3_mk_false(self._context.ref()), self._context) - elif isinstance(obj, (numbers.Number, str)) or ( + elif isinstance(obj, numbers.Number | str) or ( hasattr(obj, "__module__") and obj.__module__ in ("z3", "z3.z3") ): return obj @@ -820,7 +820,7 @@ def _batch_eval(self, exprs, n, extra_constraints=(), solver=None, model_callbac # construct results r = [] for expr in exprs: - if not isinstance(expr, (numbers.Number, str, bool)): + if not isinstance(expr, numbers.Number | str | bool): v = self._primitive_from_model(model, expr) r.append(v) else: diff --git a/claripy/balancer.py b/claripy/balancer.py index 626f5598c..20694c7d1 100644 --- a/claripy/balancer.py +++ b/claripy/balancer.py @@ -1,6 +1,5 @@ import logging import operator -from typing import Set from . import _all_operations, vsa from .ast.base import Base @@ -320,7 +319,7 @@ def _get_assumptions(t): # Truism extractor # - def _unpack_truisms(self, c) -> Set: + def _unpack_truisms(self, c) -> set: """ Given a constraint, _unpack_truisms() returns a set of constraints that must be True for this constraint to be True. diff --git a/claripy/frontend_mixins/constraint_fixer_mixin.py b/claripy/frontend_mixins/constraint_fixer_mixin.py index a224f9a50..7413d2ddb 100644 --- a/claripy/frontend_mixins/constraint_fixer_mixin.py +++ b/claripy/frontend_mixins/constraint_fixer_mixin.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, List, Set, Tuple, Union +from typing import TYPE_CHECKING, Union from claripy import BoolV @@ -7,8 +7,8 @@ class ConstraintFixerMixin: - def add(self, constraints: Union["Bool", List["Bool"], Set["Bool"], Tuple["Bool", ...]], **kwargs) -> List["Bool"]: - constraints = [constraints] if not isinstance(constraints, (list, tuple, set)) else constraints + def add(self, constraints: Union["Bool", list["Bool"], set["Bool"], tuple["Bool", ...]], **kwargs) -> list["Bool"]: + constraints = [constraints] if not isinstance(constraints, list | tuple | set) else constraints if len(constraints) == 0: return [] diff --git a/claripy/frontend_mixins/model_cache_mixin.py b/claripy/frontend_mixins/model_cache_mixin.py index 2d7b7e7c0..9c7d89ed3 100644 --- a/claripy/frontend_mixins/model_cache_mixin.py +++ b/claripy/frontend_mixins/model_cache_mixin.py @@ -1,6 +1,5 @@ import itertools import weakref -from typing import Tuple from claripy import backends, errors, false from claripy.ast import Base, all_operations @@ -102,7 +101,7 @@ def eval_constraints(self, constraints): except errors.ClaripyZeroDivisionError: return False - def eval_list(self, asts, allow_unconstrained: bool = True) -> Tuple: + def eval_list(self, asts, allow_unconstrained: bool = True) -> tuple: """ Evaluate a list of ASTs. diff --git a/claripy/frontends/composite_frontend.py b/claripy/frontends/composite_frontend.py index 78fe9d2e6..381828100 100644 --- a/claripy/frontends/composite_frontend.py +++ b/claripy/frontends/composite_frontend.py @@ -1,7 +1,7 @@ import itertools import logging import weakref -from typing import TYPE_CHECKING, Set +from typing import TYPE_CHECKING from claripy import backends from claripy.ast import Base @@ -113,7 +113,7 @@ def _solvers_for_variables(self, names): return existing_solvers @staticmethod - def _names_for(names=None, lst=None, lst2=None, e=None, v=None) -> Set[str]: + def _names_for(names=None, lst=None, lst2=None, e=None, v=None) -> set[str]: if names is None: names = set() if e is not None and isinstance(e, Base): @@ -133,7 +133,7 @@ def _names_for(names=None, lst=None, lst2=None, e=None, v=None) -> Set[str]: def _merged_solver_for(self, *args, **kwargs): return self._solver_for_names(self._names_for(*args, **kwargs)) - def _solver_for_names(self, names: Set[str]) -> "SolverCompositeChild": + def _solver_for_names(self, names: set[str]) -> "SolverCompositeChild": """ Get a merged child solver for variables specified in `names`. diff --git a/claripy/frontends/full_frontend.py b/claripy/frontends/full_frontend.py index 306c06305..4730cc857 100644 --- a/claripy/frontends/full_frontend.py +++ b/claripy/frontends/full_frontend.py @@ -1,6 +1,7 @@ import logging import threading -from typing import TYPE_CHECKING, Any, Iterable, List, Optional, Tuple, TypeVar, overload +from collections.abc import Iterable +from typing import TYPE_CHECKING, Any, Optional, TypeVar, overload from claripy.ast.bv import SGE, SLE, UGE, ULE from claripy.backend_manager import backends @@ -99,12 +100,12 @@ def _add_constraints(self): # Constraint management # - def add(self, constraints: List["Bool"]) -> List["Bool"]: + def add(self, constraints: list["Bool"]) -> list["Bool"]: to_add = ConstrainedFrontend.add(self, constraints) self._to_add += to_add return to_add - def simplify(self) -> List["Bool"]: + def simplify(self) -> list["Bool"]: ConstrainedFrontend.simplify(self) # TODO: should we do this? @@ -121,7 +122,7 @@ def check_satisfiability(self, extra_constraints=(), exact=None) -> bool: except BackendError as e: raise ClaripyFrontendError("Backend error during solve") from e - def satisfiable(self, extra_constraints: Iterable["Bool"] = (), exact: Optional[bool] = None) -> bool: + def satisfiable(self, extra_constraints: Iterable["Bool"] = (), exact: bool | None = None) -> bool: try: return self._solver_backend.satisfiable( extra_constraints=extra_constraints, solver=self._get_solver(), model_callback=self._model_hook @@ -131,20 +132,20 @@ def satisfiable(self, extra_constraints: Iterable["Bool"] = (), exact: Optional[ @overload def eval( - self, e: "BV", n: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... - ) -> Tuple[int, ...]: ... + self, e: "BV", n: int, extra_constraints: tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... + ) -> tuple[int, ...]: ... @overload def eval( - self, e: "Bool", n: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... - ) -> Tuple[bool, ...]: ... + self, e: "Bool", n: int, extra_constraints: tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... + ) -> tuple[bool, ...]: ... @overload def eval( - self, e: "FP", n: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... - ) -> Tuple[float, ...]: ... + self, e: "FP", n: int, extra_constraints: tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... + ) -> tuple[float, ...]: ... - def eval(self, e, n, extra_constraints=(), exact=None) -> Tuple[Any, ...]: + def eval(self, e, n, extra_constraints=(), exact=None) -> tuple[Any, ...]: try: results = tuple( self._solver_backend.eval( @@ -165,18 +166,18 @@ def eval(self, e, n, extra_constraints=(), exact=None) -> Tuple[Any, ...]: # if you need another overload, add one @overload def batch_eval( - self, exprs: Iterable["BV"], n: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional[bool] = ... - ) -> List[Tuple[int, ...]]: ... + self, exprs: Iterable["BV"], n: int, extra_constraints: tuple["Bool", ...] = ..., exact: bool | None = ... + ) -> list[tuple[int, ...]]: ... @overload def batch_eval( - self, exprs: Iterable["Bool"], n: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional[bool] = ... - ) -> List[Tuple[bool, ...]]: ... + self, exprs: Iterable["Bool"], n: int, extra_constraints: tuple["Bool", ...] = ..., exact: bool | None = ... + ) -> list[tuple[bool, ...]]: ... @overload def batch_eval( - self, exprs: Iterable["FP"], n: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional[bool] = ... - ) -> List[Tuple[float, ...]]: ... + self, exprs: Iterable["FP"], n: int, extra_constraints: tuple["Bool", ...] = ..., exact: bool | None = ... + ) -> list[tuple[float, ...]]: ... def batch_eval(self, exprs, n, extra_constraints=(), exact=None): try: @@ -195,17 +196,17 @@ def batch_eval(self, exprs, n, extra_constraints=(), exact=None): @overload def max( - self, e: "BV", extra_constraints: Tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... + self, e: "BV", extra_constraints: tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... ) -> int: ... @overload def max( - self, e: "Bool", extra_constraints: Tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... + self, e: "Bool", extra_constraints: tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... ) -> bool: ... @overload def max( - self, e: "FP", extra_constraints: Tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... + self, e: "FP", extra_constraints: tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... ) -> float: ... def max(self, e, extra_constraints=(), signed=False, exact=None): @@ -238,17 +239,17 @@ def max(self, e, extra_constraints=(), signed=False, exact=None): @overload def min( - self, e: "BV", extra_constraints: Tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... + self, e: "BV", extra_constraints: tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... ) -> int: ... @overload def min( - self, e: "Bool", extra_constraints: Tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... + self, e: "Bool", extra_constraints: tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... ) -> bool: ... @overload def min( - self, e: "FP", extra_constraints: Tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... + self, e: "FP", extra_constraints: tuple["Bool", ...] = ..., signed: bool = ..., exact: Optional["Bool"] = ... ) -> float: ... def min(self, e, extra_constraints=(), signed=False, exact=None): @@ -281,17 +282,17 @@ def min(self, e, extra_constraints=(), signed=False, exact=None): @overload def solution( - self, e: "BV", v: int, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... + self, e: "BV", v: int, extra_constraints: tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... ) -> bool: ... @overload def solution( - self, e: "Bool", v: bool, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... + self, e: "Bool", v: bool, extra_constraints: tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... ) -> bool: ... @overload def solution( - self, e: "FP", v: float, extra_constraints: Tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... + self, e: "FP", v: float, extra_constraints: tuple["Bool", ...] = ..., exact: Optional["Bool"] = ... ) -> bool: ... def solution(self, e, v, extra_constraints=(), exact=None): @@ -302,13 +303,13 @@ def solution(self, e, v, extra_constraints=(), exact=None): except BackendError as exc: raise ClaripyFrontendError("Backend error during solution") from exc - def is_true(self, e: "Bool", extra_constraints: Tuple["Bool", ...] = (), exact: Optional[bool] = None) -> bool: + def is_true(self, e: "Bool", extra_constraints: tuple["Bool", ...] = (), exact: bool | None = None) -> bool: return e.is_true() - def is_false(self, e: "Bool", extra_constraints: Tuple["Bool", ...] = (), exact: Optional[bool] = None) -> bool: + def is_false(self, e: "Bool", extra_constraints: tuple["Bool", ...] = (), exact: bool | None = None) -> bool: return e.is_false() - def unsat_core(self, extra_constraints: Tuple["Bool", ...] = ()) -> Iterable["Bool"]: + def unsat_core(self, extra_constraints: tuple["Bool", ...] = ()) -> Iterable["Bool"]: if self.satisfiable(extra_constraints=extra_constraints): # all constraints are satisfied return () @@ -330,7 +331,7 @@ def downsize(self) -> None: # Merging and splitting # - def merge(self: T, others, merge_conditions, common_ancestor=None) -> Tuple[bool, T]: + def merge(self: T, others, merge_conditions, common_ancestor=None) -> tuple[bool, T]: return ( self._solver_backend.__class__.__name__ == "BackendZ3", ConstrainedFrontend.merge(self, others, merge_conditions, common_ancestor=common_ancestor)[1], diff --git a/claripy/simplifications.py b/claripy/simplifications.py index 2e7f6cdb6..089b8a650 100644 --- a/claripy/simplifications.py +++ b/claripy/simplifications.py @@ -3,7 +3,6 @@ import itertools import operator from functools import reduce -from typing import Optional from . import ast, fp from .backend_manager import backends @@ -1023,7 +1022,7 @@ def and_mask_comparing_against_constant_simplifier(op, a, b): # the high `zero_bits` bits are zero # check the constant b_higher = b[b.size() - 1 : b.size() - zero_bits] - b_higher_bits_are_0: Optional[bool] = None + b_higher_bits_are_0: bool | None = None if (b_higher == 0).is_true(): b_higher_bits_are_0 = True elif (b_higher == 0).is_false(): diff --git a/claripy/utils/deprecated.py b/claripy/utils/deprecated.py index dc27248c6..6a785bfe5 100644 --- a/claripy/utils/deprecated.py +++ b/claripy/utils/deprecated.py @@ -1,8 +1,7 @@ import warnings -from typing import Optional -def deprecated(new: str, old: Optional[str] = None): +def deprecated(new: str, old: str | None = None): """ Warn a user once that a function has been deprecated If old is not specified, func.__name__ is used as the old name diff --git a/claripy/vsa/bool_result.py b/claripy/vsa/bool_result.py index be39f75d3..d52f81b1b 100644 --- a/claripy/vsa/bool_result.py +++ b/claripy/vsa/bool_result.py @@ -112,7 +112,7 @@ def __and__(self, other): def union(self, other): if other is True or isinstance(other, TrueResult): return TrueResult() - elif other is False or isinstance(other, (FalseResult, MaybeResult)): + elif other is False or isinstance(other, FalseResult | MaybeResult): return MaybeResult() else: return NotImplemented diff --git a/claripy/vsa/discrete_strided_interval_set.py b/claripy/vsa/discrete_strided_interval_set.py index 6f809e19c..897e6fa91 100644 --- a/claripy/vsa/discrete_strided_interval_set.py +++ b/claripy/vsa/discrete_strided_interval_set.py @@ -36,7 +36,7 @@ def operator(self, o=None): ret = DiscreteStridedIntervalSet(bits=self.bits, si_set=new_si_set) return ret.normalize() - elif isinstance(o, (StridedInterval, numbers.Number, BVV)): + elif isinstance(o, StridedInterval | numbers.Number | BVV): new_si_set = set() for si in self._si_set: new_si_set.add(getattr(si, f.__name__)(o)) diff --git a/claripy/vsa/strided_interval.py b/claripy/vsa/strided_interval.py index 1253ee21e..e83eb946b 100644 --- a/claripy/vsa/strided_interval.py +++ b/claripy/vsa/strided_interval.py @@ -38,7 +38,7 @@ def normalizer(self, o): if f.__name__ == "union" and isinstance(o, DiscreteStridedIntervalSet): return o.union(self) - if isinstance(o, (ValueSet, DiscreteStridedIntervalSet)): + if isinstance(o, ValueSet | DiscreteStridedIntervalSet): # if it's singlevalued, we can convert it to a StridedInterval if o.cardinality == 1: o = o.stridedinterval() @@ -3573,7 +3573,7 @@ def CreateStridedInterval( # No conversion will be done return to_conv - if not isinstance(to_conv, (numbers.Number, BVV)): + if not isinstance(to_conv, numbers.Number | BVV): raise ClaripyOperationError(f"Unsupported to_conv type {type(to_conv)}") if stride is not None or lower_bound is not None or upper_bound is not None: diff --git a/pyproject.toml b/pyproject.toml index 3dcd5ae70..f365de0ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ line-length = 120 target-version = ['py310'] [tool.ruff] +target-version = "py310" line-length = 120 [tool.ruff.lint]