openai/openai-python

Public

mirrored from https://github.com/openai/openai-pythonAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
98925cef766fc8d1adaaed9013ad43a44739edef

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/openai/_utils/_typing.py

151lines · modecode

1from __future__ import annotations
2
3import sys
4import typing
5import typing_extensions
6from typing import Any, TypeVar, Iterable, cast
7from collections import abc as _c_abc
8from typing_extensions import (
9 TypeIs,
10 Required,
11 Annotated,
12 get_args,
13 get_origin,
14)
15
16from ._utils import lru_cache
17from .._types import InheritsGeneric
18from .._compat import is_union as _is_union
19
20
21def is_annotated_type(typ: type) -> bool:
22 return get_origin(typ) == Annotated
23
24
25def is_list_type(typ: type) -> bool:
26 return (get_origin(typ) or typ) == list
27
28
29def is_iterable_type(typ: type) -> bool:
30 """If the given type is `typing.Iterable[T]`"""
31 origin = get_origin(typ) or typ
32 return origin == Iterable or origin == _c_abc.Iterable
33
34
35def is_union_type(typ: type) -> bool:
36 return _is_union(get_origin(typ))
37
38
39def is_required_type(typ: type) -> bool:
40 return get_origin(typ) == Required
41
42
43def is_typevar(typ: type) -> bool:
44 # type ignore is required because type checkers
45 # think this expression will always return False
46 return type(typ) == TypeVar # type: ignore
47
48
49_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,)
50if sys.version_info >= (3, 12):
51 _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType)
52
53
54def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]:
55 """Return whether the provided argument is an instance of `TypeAliasType`.
56
57 ```python
58 type Int = int
59 is_type_alias_type(Int)
60 # > True
61 Str = TypeAliasType("Str", str)
62 is_type_alias_type(Str)
63 # > True
64 ```
65 """
66 return isinstance(tp, _TYPE_ALIAS_TYPES)
67
68
69# Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]]
70@lru_cache(maxsize=8096)
71def strip_annotated_type(typ: type) -> type:
72 if is_required_type(typ) or is_annotated_type(typ):
73 return strip_annotated_type(cast(type, get_args(typ)[0]))
74
75 return typ
76
77
78def extract_type_arg(typ: type, index: int) -> type:
79 args = get_args(typ)
80 try:
81 return cast(type, args[index])
82 except IndexError as err:
83 raise RuntimeError(f"Expected type {typ} to have a type argument at index {index} but it did not") from err
84
85
86def extract_type_var_from_base(
87 typ: type,
88 *,
89 generic_bases: tuple[type, ...],
90 index: int,
91 failure_message: str | None = None,
92) -> type:
93 """Given a type like `Foo[T]`, returns the generic type variable `T`.
94
95 This also handles the case where a concrete subclass is given, e.g.
96 ```py
97 class MyResponse(Foo[bytes]):
98 ...
99
100 extract_type_var(MyResponse, bases=(Foo,), index=0) -> bytes
101 ```
102
103 And where a generic subclass is given:
104 ```py
105 _T = TypeVar('_T')
106 class MyResponse(Foo[_T]):
107 ...
108
109 extract_type_var(MyResponse[bytes], bases=(Foo,), index=0) -> bytes
110 ```
111 """
112 cls = cast(object, get_origin(typ) or typ)
113 if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains]
114 # we're given the class directly
115 return extract_type_arg(typ, index)
116
117 # if a subclass is given
118 # ---
119 # this is needed as __orig_bases__ is not present in the typeshed stubs
120 # because it is intended to be for internal use only, however there does
121 # not seem to be a way to resolve generic TypeVars for inherited subclasses
122 # without using it.
123 if isinstance(cls, InheritsGeneric):
124 target_base_class: Any | None = None
125 for base in cls.__orig_bases__:
126 if base.__origin__ in generic_bases:
127 target_base_class = base
128 break
129
130 if target_base_class is None:
131 raise RuntimeError(
132 "Could not find the generic base class;\n"
133 "This should never happen;\n"
134 f"Does {cls} inherit from one of {generic_bases} ?"
135 )
136
137 extracted = extract_type_arg(target_base_class, index)
138 if is_typevar(extracted):
139 # If the extracted type argument is itself a type variable
140 # then that means the subclass itself is generic, so we have
141 # to resolve the type argument from the class itself, not
142 # the base class.
143 #
144 # Note: if there is more than 1 type argument, the subclass could
145 # change the ordering of the type arguments, this is not currently
146 # supported.
147 return extract_type_arg(typ, index)
148
149 return extracted
150
151 raise RuntimeError(failure_message or f"Could not resolve inner type variable at index {index} for {typ}")
152