pyanalyze.value

Value classes represent the value of an expression in a Python program. Values are the key data type used in pyanalyze’s internals.

Values are instances of a subclass of Value. This module defines these subclasses and some related utilities.

dump_value() can be used to show inferred values during type checking. Examples:

from typing import Any
from pyanalyze import dump_value

def function(x: int, y: list[int], z: Any):
    dump_value(1)  # Literal[1]
    dump_value(x)  # int
    dump_value(y)  # list[int]
    dump_value(z)  # Any
class pyanalyze.value.Value

Base class for all values.

can_assign(other: Value, ctx: CanAssignContext) CanAssignError

Whether other can be assigned to self.

If yes, return a (possibly empty) map with the TypeVar values dictated by the assignment. If not, return a CanAssignError explaining why the types are not compatible.

For example, calling a.can_assign(b, ctx) where a is Iterable[T] and b is List[int] will return {T: TypedValue(int)}.

This is the primary mechanism used for checking type compatibility.

is_assignable(other: Value, ctx: CanAssignContext) bool

Similar to can_assign() but returns a bool for simplicity.

walk_values() Iterable[Value]

Iterator that yields all sub-values contained in this value.

substitute_typevars(typevars: Value')]) Value

Substitute the typevars in the map to produce a new Value.

This is used to specialize a generic. For example, substituting {T: int} on List[T] will produce List[int].

is_type(typ: type) bool

Returns whether this value is an instance of the given type.

This method should be avoided. Use can_assign() instead for checking compatibility.

get_type() type | None

Returns the type of this value, or None if it is not known.

This method should be avoided.

get_type_value() Value

Return the type of this object as used for dunder lookups.

simplify() Value

Simplify this Value to reduce excessive detail.

class pyanalyze.value.CanAssignContext(*args, **kwargs)

A context passed to the Value.can_assign() method.

Provides access to various functionality used for type checking.

make_type_object(typ: type | super | str) TypeObject

Return a pyanalyze.type_object.TypeObject for this concrete type.

get_generic_bases(typ: type | str, generic_args: Sequence[Value] = ()) Value')]]

Return the base classes for typ with their generic arguments.

For example, calling ctx.get_generic_bases(dict, [TypedValue(int), TypedValue(str)]) may produce a map containing the following:

{
    dict: [TypedValue(int), TypedValue(str)],
    Mapping: [TypedValue(int), TypedValue(str)],
    Iterable: [TypedValue(int)],
    Sized: [],
}
get_signature(obj: object) Signature | OverloadedSignature | None

Return a pyanalyze.signature.Signature for this object.

Return None if the object is not callable.

signature_from_value(value: Value) None | Signature | BoundMethodSignature | OverloadedSignature

Return a pyanalyze.signature.Signature for a Value.

Return None if the object is not callable.

has_used_any_match() bool

Whether Any was used to secure a match.

record_any_used() None

Record that Any was used to secure a match.

reset_any_used() ContextManager[None]

Context that resets the value used by has_used_any_match() and record_any_match().

set_exclude_any() ContextManager[None]

Within this context, Any is compatible only with itself.

should_exclude_any() bool

Whether Any should be compatible only with itself.

display_value(value: Value) str

Provide a pretty, user-readable display of this value.

class pyanalyze.value.CanAssignError(message: str = '', children: ~typing.List[~pyanalyze.value.CanAssignError] = <factory>, error_code: ~pyanalyze.error_code.Error | None = None)

A type checking error message with nested details.

This exists in order to produce more useful error messages when there is a mismatch between complex types.

display(depth: int = 2) str

Display all errors in a human-readable format.

pyanalyze.value.assert_is_value(obj: object, value: Value, *, skip_annotated: bool = False) None

Used to test pyanalyze’s value inference.

Takes two arguments: a Python object and a Value object. At runtime this does nothing, but pyanalyze throws an error if the object is not inferred to be the same as the Value.

Example usage:

assert_is_value(1, KnownValue(1))  # passes
assert_is_value(1, TypedValue(int))  # shows an error

If skip_annotated is True, unwraps any AnnotatedValue in the input.

pyanalyze.value.dump_value(value: T) T

Print out the Value representation of its argument.

Calling it will make pyanalyze print out an internal representation of the argument’s inferred value. Use pyanalyze.extensions.reveal_type() for a more user-friendly representation.

At runtime this returns the argument unchanged.

class pyanalyze.value.AnySource(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Sources of Any values.

default = 1

Any that has not been categorized.

explicit = 2

The user wrote ‘Any’ in an annotation.

error = 3

An error occurred.

unreachable = 4

Value that is inferred to be unreachable.

inference = 5

Insufficiently powerful type inference.

unannotated = 6

Unannotated code.

variable_name = 7

A VariableNameValue.

from_another = 8

An Any derived from another Any, for example as an attribute.

generic_argument = 9

Missing type argument to a generic class.

marker = 10

Marker object used internally.

incomplete_annotation = 11

A special form like ClassVar without a type argument.

multiple_overload_matches = 12

Multiple matching overloads.

ellipsis_callable = 13

Callable using an ellipsis.

unresolved_import = 14

An unresolved import.

class pyanalyze.value.AnyValue(source: AnySource)

An unknown value, equivalent to typing.Any.

source: AnySource

The source of this value, such as a user-defined annotation or a previous error.

pyanalyze.value.UNRESOLVED_VALUE = AnyValue(source=<AnySource.default: 1>)

The default instance of AnyValue.

In the future, this should be replaced with instances of AnyValue with a specific source.

class pyanalyze.value.VoidValue

Dummy Value used as the inferred type of AST nodes that do not represent expressions.

This is useful so that we can infer a Value for every AST node, but notice if we unexpectedly use it like an actual value.

class pyanalyze.value.TypeAlias(evaluator: Callable[[], pyanalyze.value.Value], evaluate_type_params: Callable[[], Sequence[Union[ExternalType(type_path='TypeVar'), ExternalType(type_path='typing_extensions.TypeVar'), ExternalType(type_path='ParamSpec'), ExternalType(type_path='typing_extensions.ParamSpec'), ExternalType(type_path='TypeVarTuple'), ExternalType(type_path='typing_extensions.TypeVarTuple')]]], evaluated_value: pyanalyze.value.Value | None = None, type_params: Optional[Sequence[Union[ExternalType(type_path='TypeVar'), ExternalType(type_path='typing_extensions.TypeVar'), ExternalType(type_path='ParamSpec'), ExternalType(type_path='typing_extensions.ParamSpec'), ExternalType(type_path='TypeVarTuple'), ExternalType(type_path='typing_extensions.TypeVarTuple')]]] = None)
evaluator: Callable[[], Value]

Callable that evaluates the value.

evaluate_type_params: TypeVarTuple')]]

Callable that evaluates the type parameters.

evaluated_value: Value | None = None

Value that the type alias evaluates to.

type_params: TypeVarTuple')] | None = None

Type parameters of the type alias.

class pyanalyze.value.TypeAliasValue(name: str, module: str, alias: TypeAlias, type_arguments: Sequence[Value] = ())

Value representing a type alias.

name: str

Name of the type alias.

module: str

Module where the type alias is defined.

class pyanalyze.value.UninitializedValue

Value for variables that have not been initialized.

Usage of variables with this value should be an error.

pyanalyze.value.UNINITIALIZED_VALUE = UninitializedValue()

The only instance of UninitializedValue.

class pyanalyze.value.KnownValue(val: Any)

Equivalent to typing.Literal. Represents a specific value.

This is inferred for constants and for references to objects like modules, classes, and functions.

val: Any

The Python object that this KnownValue represents.

class pyanalyze.value.KnownValueWithTypeVars(val: Any, typevars: Value')])

Subclass of KnownValue that records a TypeVar substitution.

typevars: Value')]

TypeVars substituted on this value.

class pyanalyze.value.SyntheticModuleValue(module_path: Sequence[str])

Represents a module that exists only in stub files.

class pyanalyze.value.UnboundMethodValue(attr_name: str, composite: Composite, secondary_attr_name: str | None = None, typevars: Value')] | None = None)

Value that represents a method on an underlying Value.

Despite the name this really represents a method bound to a value. For example, given s: str, s.strip will be inferred as UnboundMethodValue("strip", Composite(TypedValue(str), "s")).

attr_name: str

Name of the method.

composite: Composite

Value the method is bound to.

secondary_attr_name: str | None = None

Used when an attribute is accessed on an existing UnboundMethodValue.

This is mostly useful in conjunction with asynq, where we might use object.method.asynq. In that case, we would infer an UnboundMethodValue with secondary_attr_name set to "asynq".

typevars: Value')] | None = None

Extra TypeVars applied to this method.

get_method() Any | None

Return the runtime callable for this UnboundMethodValue, or None if it cannot be found.

class pyanalyze.value.TypedValue(typ: type | str, literal_only: bool = False)

Value for which we know the type. This is equivalent to simple type annotations: an annotation of int will yield TypedValue(int) during type inference.

typ: type | str

The underlying type, or a fully qualified reference to one.

literal_only: bool = False

True if this is LiteralString (PEP 675).

class pyanalyze.value.NewTypeValue(newtype: Any)

A wrapper around an underlying type.

Corresponds to typing.NewType.

This is a subclass of TypedValue. Currently only NewTypes over simple, non-generic types are supported.

name: str

Name of the NewType.

newtype: Any

Underlying NewType object.

class pyanalyze.value.GenericValue(typ: type | str, args: Iterable[Value])

Subclass of TypedValue that can represent generics.

For example, List[int] is represented as GenericValue(list, [TypedValue(int)]).

args: Tuple[Value, ...]

The generic arguments to the type.

class pyanalyze.value.SequenceValue(typ: type | str, members: Sequence[Tuple[bool, Value]])

A TypedValue subclass representing a sequence of known type.

This is represented as a sequence, but each entry in the sequence may consist of multiple values. For example, the expression [int(self.foo)] may be typed as SequenceValue(list, [(False, TypedValue(int))]). The expression ["x", *some_str.split()] would be represented as SequenceValue(list, [(False, KnownValue("x")), (True, TypedValue(str))]).

This is only used for set, list, and tuple.

members: Tuple[Tuple[bool, Value], ...]

The elements of the sequence.

get_member_sequence() Sequence[Value] | None

Return the Value objects in this sequence. Return None if there are any unpacked values in the sequence.

make_known_value() Value

Turn this value into a KnownValue if possible.

class pyanalyze.value.KVPair(key: Value, value: Value, is_many: bool = False, is_required: bool = True)

Represents a single entry in a DictIncompleteValue.

key: Value

Represents the key.

value: Value

Represents the value.

is_many: bool = False

Whether this key-value pair represents possibly multiple keys.

is_required: bool = True

Whether this key-value pair is definitely present.

class pyanalyze.value.DictIncompleteValue(typ: type | str, kv_pairs: Sequence[KVPair])

A TypedValue representing a dictionary of known size.

For example, the expression {'foo': int(self.bar)} may be typed as DictIncompleteValue(dict, [KVPair(KnownValue('foo'), TypedValue(int))]).

kv_pairs: Tuple[KVPair, ...]

Sequence of KVPair objects representing the keys and values of the dict.

property items: Sequence[Tuple[Value, Value]]

Sequence of pairs representing the keys and values of the dict.

get_value(key: Value, ctx: CanAssignContext) Value

Return the Value for a specific key.

class pyanalyze.value.TypedDictEntry(typ: pyanalyze.value.Value, required: bool = True, readonly: bool = False)
class pyanalyze.value.TypedDictValue(items: Dict[str, TypedDictEntry], extra_keys: Value | None = None, extra_keys_readonly: bool = False)

Equivalent to typing.TypedDict; a dictionary with a known set of string keys.

items: Dict[str, TypedDictEntry]

The items of the TypedDict. Required items are represented as (True, value) and optional ones as (False, value).

extra_keys: Value | None = None

The type of unknown keys, if any.

extra_keys_readonly: bool = False

Whether the extra keys are readonly.

class pyanalyze.value.AsyncTaskIncompleteValue(typ: type | str, value: Value)

A GenericValue representing an async task.

This should probably just be replaced with GenericValue.

value: Value

The value returned by the task on completion.

class pyanalyze.value.CallableValue(signature: ~pyanalyze.signature.Signature | ~pyanalyze.signature.OverloadedSignature, fallback: type | str = <class 'collections.abc.Callable'>)

Equivalent to the Callable type.

This is a thin wrapper around pyanalyze.signature.Signature.

get_asynq_value() Value

Return the CallableValue for the .asynq attribute of an AsynqCallable.

class pyanalyze.value.SubclassValue(typ: TypedValue | TypeVarValue, exactly: bool = False)

Equivalent of Type[].

The typ attribute can be either a TypedValue or a TypeVarValue. The former is equivalent to Type[int] and represents the int class or a subclass. The latter is equivalent to Type[T] where T is a type variable. The third legal argument to Type[] is Any, but Type[Any] is represented as TypedValue(type).

typ: TypedValue | TypeVarValue

The underlying type.

exactly: bool = False

If True, represents exactly this class and not a subclass.

class pyanalyze.value.MultiValuedValue(raw_vals: dataclasses.InitVar[Iterable[pyanalyze.value.Value]])

Equivalent of typing.Union. Represents the union of multiple values.

vals: Tuple[Value, ...]

The underlying values of the union.

pyanalyze.value.NO_RETURN_VALUE = MultiValuedValue(vals=())

The empty union, equivalent to typing.Never.

class pyanalyze.value.ReferencingValue(scope: Any, name: str)

Value that is a reference to another value (used to implement globals).

class pyanalyze.value.Bound
class pyanalyze.value.LowerBound(typevar: ExternalType(type_path='typing.TypeVar') | ExternalType(type_path='typing_extensions.TypeVar') | ExternalType(type_path='typing.ParamSpec') | ExternalType(type_path='typing_extensions.ParamSpec') | ExternalType(type_path='typing.TypeVarTuple') | ExternalType(type_path='typing_extensions.TypeVarTuple'), value: Value)

LowerBound(T, V) means V must be assignable to the value of T.

class pyanalyze.value.UpperBound(typevar: ExternalType(type_path='typing.TypeVar') | ExternalType(type_path='typing_extensions.TypeVar') | ExternalType(type_path='typing.ParamSpec') | ExternalType(type_path='typing_extensions.ParamSpec') | ExternalType(type_path='typing.TypeVarTuple') | ExternalType(type_path='typing_extensions.TypeVarTuple'), value: Value)

UpperBound(T, V) means the value of T must be assignable to V.

class pyanalyze.value.OrBound(bounds: Sequence[Sequence[Bound]])

At least one of the specified bounds must be true.

class pyanalyze.value.IsOneOf(typevar: Union[ExternalType(type_path='TypeVar'), ExternalType(type_path='typing_extensions.TypeVar'), ExternalType(type_path='ParamSpec'), ExternalType(type_path='typing_extensions.ParamSpec'), ExternalType(type_path='TypeVarTuple'), ExternalType(type_path='typing_extensions.TypeVarTuple')], constraints: Sequence[pyanalyze.value.Value])
class pyanalyze.value.TypeVarValue(typevar: ExternalType(type_path='typing.TypeVar') | ExternalType(type_path='typing_extensions.TypeVar') | ExternalType(type_path='typing.ParamSpec') | ExternalType(type_path='typing_extensions.ParamSpec') | ExternalType(type_path='typing.TypeVarTuple') | ExternalType(type_path='typing_extensions.TypeVarTuple'), bound: Value | None = None, constraints: Sequence[Value] = (), is_paramspec: bool = False, is_typevartuple: bool = False)

Value representing a typing.TypeVar or typing.ParamSpec.

Currently, variance is ignored.

class pyanalyze.value.ParamSpecArgsValue(param_spec: typing_extensions.ParamSpec)
class pyanalyze.value.ParamSpecKwargsValue(param_spec: typing_extensions.ParamSpec)
class pyanalyze.value.Extension

An extra piece of information about a type that can be stored in an AnnotatedValue.

class pyanalyze.value.CustomCheckExtension(custom_check: pyanalyze.extensions.CustomCheck)
class pyanalyze.value.ParameterTypeGuardExtension(varname: str, guarded_type: Value)

An Extension used in a function return type. Used to indicate that the parameter named varname is of type guarded_type.

Corresponds to pyanalyze.extensions.ParameterTypeGuard.

class pyanalyze.value.NoReturnGuardExtension(varname: str, guarded_type: Value)

An Extension used in a function return type. Used to indicate that unless the parameter named varname is of type guarded_type, the function does not return.

Corresponds to pyanalyze.extensions.NoReturnGuard.

class pyanalyze.value.TypeGuardExtension(guarded_type: Value)

An Extension used in a function return type. Used to indicate that the first function argument is of type guarded_type.

Corresponds to pyanalyze.extensions.TypeGuard, or typing.TypeGuard.

class pyanalyze.value.TypeIsExtension(guarded_type: Value)

An Extension used in a function return type. Used to indicate that the first function argument may be narrowed to type guarded_type.

Corresponds to typing_extensions.TypeIs (see PEP 742).

class pyanalyze.value.HasAttrGuardExtension(varname: str, attribute_name: Value, attribute_type: Value)

An Extension used in a function return type. Used to indicate that the function argument named varname has an attribute named attribute_name of type attribute_type.

Corresponds to pyanalyze.extensions.HasAttrGuard.

class pyanalyze.value.HasAttrExtension(attribute_name: Value, attribute_type: Value)

Attached to an object to indicate that it has the given attribute.

These cannot be created directly from user code, only through the pyanalyze.extension.HasAttrGuard mechanism. This is because of potential code like this:

def f(x: Annotated[object, HasAttr["y", int]]) -> None:
    return x.y

Here, we would correctly type check the function body, but we currently have no way to enforce that the function is only called with arguments that obey the constraint.

class pyanalyze.value.ConstraintExtension(constraint: AbstractConstraint)

Encapsulates a Constraint. If the value is evaluated and is truthy, the constraint must be True.

class pyanalyze.value.NoReturnConstraintExtension(constraint: AbstractConstraint)

Encapsulates a Constraint. If the value is evaluated and completes, the constraint must be True.

class pyanalyze.value.AlwaysPresentExtension

Extension that indicates that an iterable value is nonempty.

Currently cannot be used from user code.

class pyanalyze.value.AssertErrorExtension

Used for the implementation of pyanalyze.extensions.assert_error().

class pyanalyze.value.SkipDeprecatedExtension

Indicates that use of this value should not trigger deprecation errors.

class pyanalyze.value.DeprecatedExtension(deprecation_message: str)

Indicates that use of this value should trigger a deprecation error.

class pyanalyze.value.SysPlatformExtension

Used for sys.platform.

class pyanalyze.value.SysVersionInfoExtension

Used for sys.version_info.

class pyanalyze.value.DefiniteValueExtension(value: bool)

Used if a comparison has a definite value that should be used to skip type checking.

class pyanalyze.value.AnnotatedValue(value: Value, metadata: Sequence[Value | Extension])

Value representing a PEP 593 Annotated object.

Pyanalyze uses Annotated types to represent types with some extra information added to them in the form of Extension objects.

value: Value

The underlying value.

metadata: Tuple[Value | Extension, ...]

The extensions associated with this value.

get_metadata_of_type(typ: Type[T]) Iterable[T]

Return any metadata of the given type.

get_custom_check_of_type(typ: Type[T]) Iterable[T]

Return any CustomChecks of the given type in the metadata.

has_metadata_of_type(typ: Type[Extension]) bool

Return whether there is metadat of the given type.

class pyanalyze.value.UnpackedValue(value: Value)

Represents the result of PEP 646’s Unpack operator.

class pyanalyze.value.VariableNameValue(varnames: Iterable[str])

Value that is stored in a variable associated with a particular kind of value.

For example, any variable named uid will get resolved into a VariableNameValue of type uid, and if it gets passed into a function that takes an argument called aid, the call will be rejected.

This was created for a legacy codebase without type annotations. If possible, prefer using NewTypes or other more explicit types.

There should only be a limited set of VariableNameValue objects, created through the pyanalyze configuration.

classmethod from_varname(varname: str, varname_map: Dict[str, VariableNameValue]) VariableNameValue | None

Returns the VariableNameValue corresponding to a variable name.

If there is no VariableNameValue that corresponds to the variable name, returns None.

pyanalyze.value.flatten_values(val: Value, *, unwrap_annotated: bool = False) Iterable[Value]

Flatten a MultiValuedValue into its constituent values.

We don’t need to do this recursively because the MultiValuedValue constructor applies this to its arguments.

if unwrap_annotated is true, produces the underlying values for AnnotatedValue objects.

pyanalyze.value.unite_values(*values: Value) Value

Unite multiple values into a single Value.

This collapses equal values and returns a MultiValuedValue if multiple remain.

pyanalyze.value.concrete_values_from_iterable(value: Value, ctx: CanAssignContext) CanAssignError | Value | Sequence[Value]

Return the exact values that can be extracted from an iterable.

Three possible return types:

  • CanAssignError if the argument is not iterable

  • A sequence of Value if we know the exact types in the iterable

  • A single Value if we just know that the iterable contains this value, but not the precise number of them.

Examples:

  • int -> CanAssignError

  • tuple[int, str] -> (int, str)

  • tuple[int, ...] -> int

pyanalyze.value.kv_pairs_from_mapping(value_val: Value, ctx: CanAssignContext) Sequence[KVPair] | CanAssignError

Return the KVPair objects that can be extracted from this value, or a CanAssignError on error.

pyanalyze.value.check_hashability(value: Value, ctx: CanAssignContext) CanAssignError | None

Check whether a value is hashable.

Return None if it is hashable, otherwise a CanAssignError.

pyanalyze.value.unpack_values(value: Value, ctx: CanAssignContext, target_length: int, post_starred_length: int | None = None) Sequence[Value] | CanAssignError

Implement iterable unpacking.

If post_starred_length is None, return a list of target_length values, or CanAssignError if value is not an iterable of the expected length. If post_starred_length is not None, return a list of target_length + 1 + post_starred_length values. This implements unpacking like a, b, *c, d = ....

pyanalyze.value.is_iterable(value: Value, ctx: CanAssignContext) CanAssignError | Value

Check whether a value is iterable.

pyanalyze.value.is_async_iterable(value: Value, ctx: CanAssignContext) CanAssignError | Value

Check whether a value is an async iterable.

pyanalyze.value.replace_known_sequence_value(value: Value) Value

Simplify a Value in a way that is easier to handle for most typechecking use cases.

Does the following:

  • Replace AnnotatedValue with its inner type

  • Replace TypeVarValue with its fallback type

  • Replace KnownValues representing list, tuples, sets, or dicts with SequenceValue or DictIncompleteValue.