Skip to content

Commit 3b18458

Browse files
authored
Bump min python to 3.9 (#121)
Bump the minimum python version in pyproject to match changes in CI test. New linting errors were solved with `ruff check --unsafe-fixes --fix` and then manually checked for accuracy.
1 parent 031f36d commit 3b18458

30 files changed

+247
-251
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ name = "guidellm"
2020
version = "0.1.0"
2121
description = "Guidance platform for deploying and managing large language models."
2222
readme = { file = "README.md", content-type = "text/markdown" }
23-
requires-python = ">=3.8.0,<4.0"
23+
requires-python = ">=3.9.0,<4.0"
2424
license = { file = "LICENSE" }
2525
authors = [ { name = "Neuralmagic, Inc." } ]
2626
urls = { homepage = "https://github.com/neuralmagic/guidellm" }
@@ -93,7 +93,7 @@ profile = "black"
9393

9494
[tool.mypy]
9595
files = ["src/guidellm", "tests"]
96-
python_version = '3.8'
96+
python_version = '3.9'
9797
warn_redundant_casts = true
9898
warn_unused_ignores = false
9999
show_error_codes = true

src/guidellm/backend/backend.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from abc import ABC, abstractmethod
2+
from collections.abc import AsyncGenerator
23
from pathlib import Path
3-
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Type, Union
4+
from typing import Any, Literal, Optional, Union
45

56
from loguru import logger
67
from PIL import Image
@@ -28,7 +29,7 @@ class Backend(ABC):
2829
:param type_: The type of the backend.
2930
"""
3031

31-
_registry: Dict[BackendType, "Type[Backend]"] = {}
32+
_registry: dict[BackendType, "type[Backend]"] = {}
3233

3334
@classmethod
3435
def register(cls, backend_type: BackendType):
@@ -46,7 +47,7 @@ def register(cls, backend_type: BackendType):
4647
if not issubclass(cls, Backend):
4748
raise TypeError("Only subclasses of Backend can be registered")
4849

49-
def inner_wrapper(wrapped_class: Type["Backend"]):
50+
def inner_wrapper(wrapped_class: type["Backend"]):
5051
cls._registry[backend_type] = wrapped_class
5152
logger.info("Registered backend type: {}", backend_type)
5253
return wrapped_class
@@ -103,7 +104,7 @@ def model(self) -> Optional[str]:
103104

104105
@property
105106
@abstractmethod
106-
def info(self) -> Dict[str, Any]:
107+
def info(self) -> dict[str, Any]:
107108
"""
108109
:return: The information about the backend.
109110
"""
@@ -146,7 +147,7 @@ async def prepare_multiprocessing(self):
146147
...
147148

148149
@abstractmethod
149-
async def available_models(self) -> List[str]:
150+
async def available_models(self) -> list[str]:
150151
"""
151152
Get the list of available models for the backend.
152153
@@ -158,7 +159,7 @@ async def available_models(self) -> List[str]:
158159
@abstractmethod
159160
async def text_completions(
160161
self,
161-
prompt: Union[str, List[str]],
162+
prompt: Union[str, list[str]],
162163
request_id: Optional[str] = None,
163164
prompt_token_count: Optional[int] = None,
164165
output_token_count: Optional[int] = None,
@@ -190,7 +191,7 @@ async def chat_completions(
190191
self,
191192
content: Union[
192193
str,
193-
List[Union[str, Dict[str, Union[str, Dict[str, str]]], Path, Image.Image]],
194+
list[Union[str, dict[str, Union[str, dict[str, str]]], Path, Image.Image]],
194195
Any,
195196
],
196197
request_id: Optional[str] = None,

src/guidellm/backend/openai.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import base64
22
import json
33
import time
4+
from collections.abc import AsyncGenerator
45
from pathlib import Path
5-
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Union
6+
from typing import Any, Literal, Optional, Union
67

78
import httpx
89
from loguru import logger
@@ -111,7 +112,7 @@ def model(self) -> Optional[str]:
111112
return self._model
112113

113114
@property
114-
def info(self) -> Dict[str, Any]:
115+
def info(self) -> dict[str, Any]:
115116
"""
116117
:return: The information about the backend.
117118
"""
@@ -157,7 +158,7 @@ async def prepare_multiprocessing(self):
157158
await self._async_client.aclose()
158159
self._async_client = None
159160

160-
async def available_models(self) -> List[str]:
161+
async def available_models(self) -> list[str]:
161162
"""
162163
Get the available models for the target server using the OpenAI models endpoint:
163164
/v1/models
@@ -176,7 +177,7 @@ async def available_models(self) -> List[str]:
176177

177178
async def text_completions( # type: ignore[override]
178179
self,
179-
prompt: Union[str, List[str]],
180+
prompt: Union[str, list[str]],
180181
request_id: Optional[str] = None,
181182
prompt_token_count: Optional[int] = None,
182183
output_token_count: Optional[int] = None,
@@ -232,7 +233,7 @@ async def chat_completions( # type: ignore[override]
232233
self,
233234
content: Union[
234235
str,
235-
List[Union[str, Dict[str, Union[str, Dict[str, str]]], Path, Image.Image]],
236+
list[Union[str, dict[str, Union[str, dict[str, str]]], Path, Image.Image]],
236237
Any,
237238
],
238239
request_id: Optional[str] = None,
@@ -318,7 +319,7 @@ def _get_async_client(self) -> httpx.AsyncClient:
318319

319320
return client
320321

321-
def _headers(self) -> Dict[str, str]:
322+
def _headers(self) -> dict[str, str]:
322323
headers = {
323324
"Content-Type": "application/json",
324325
}
@@ -335,8 +336,8 @@ def _headers(self) -> Dict[str, str]:
335336
return headers
336337

337338
def _completions_payload(
338-
self, orig_kwargs: Optional[Dict], max_output_tokens: Optional[int], **kwargs
339-
) -> Dict:
339+
self, orig_kwargs: Optional[dict], max_output_tokens: Optional[int], **kwargs
340+
) -> dict:
340341
payload = orig_kwargs or {}
341342
payload.update(kwargs)
342343
payload["model"] = self.model
@@ -366,10 +367,10 @@ def _completions_payload(
366367
def _create_chat_messages(
367368
content: Union[
368369
str,
369-
List[Union[str, Dict[str, Union[str, Dict[str, str]]], Path, Image.Image]],
370+
list[Union[str, dict[str, Union[str, dict[str, str]]], Path, Image.Image]],
370371
Any,
371372
],
372-
) -> List[Dict]:
373+
) -> list[dict]:
373374
if isinstance(content, str):
374375
return [
375376
{
@@ -382,7 +383,7 @@ def _create_chat_messages(
382383
resolved_content = []
383384

384385
for item in content:
385-
if isinstance(item, Dict):
386+
if isinstance(item, dict):
386387
resolved_content.append(item)
387388
elif isinstance(item, str):
388389
resolved_content.append({"type": "text", "text": item})
@@ -430,8 +431,8 @@ async def _iterative_completions_request(
430431
request_id: Optional[str],
431432
request_prompt_tokens: Optional[int],
432433
request_output_tokens: Optional[int],
433-
headers: Dict,
434-
payload: Dict,
434+
headers: dict,
435+
payload: dict,
435436
) -> AsyncGenerator[Union[StreamingTextResponse, ResponseSummary], None]:
436437
if type_ == "text_completions":
437438
target = f"{self.target}{TEXT_COMPLETIONS_PATH}"
@@ -551,7 +552,7 @@ async def _iterative_completions_request(
551552

552553
@staticmethod
553554
def _extract_completions_delta_content(
554-
type_: Literal["text_completions", "chat_completions"], data: Dict
555+
type_: Literal["text_completions", "chat_completions"], data: dict
555556
) -> Optional[str]:
556557
if "choices" not in data or not data["choices"]:
557558
return None
@@ -566,8 +567,8 @@ def _extract_completions_delta_content(
566567

567568
@staticmethod
568569
def _extract_completions_usage(
569-
data: Dict,
570-
) -> Optional[Dict[Literal["prompt", "output"], int]]:
570+
data: dict,
571+
) -> Optional[dict[Literal["prompt", "output"], int]]:
571572
if "usage" not in data or not data["usage"]:
572573
return None
573574

src/guidellm/backend/response.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, Literal, Optional
1+
from typing import Any, Literal, Optional
22

33
from pydantic import computed_field
44

@@ -55,8 +55,8 @@ class RequestArgs(StandardBaseModel):
5555
"""
5656

5757
target: str
58-
headers: Dict[str, str]
59-
payload: Dict[str, Any]
58+
headers: dict[str, str]
59+
payload: dict[str, Any]
6060
timeout: Optional[float] = None
6161
http2: Optional[bool] = None
6262

src/guidellm/benchmark/aggregator.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@
33
from pathlib import Path
44
from typing import (
55
Any,
6-
Dict,
76
Generic,
8-
List,
97
Literal,
108
Optional,
11-
Tuple,
129
TypeVar,
1310
Union,
1411
)
@@ -258,7 +255,7 @@ class BenchmarkAggregator(
258255
),
259256
discriminator="type_",
260257
)
261-
extras: Dict[str, Any] = Field(
258+
extras: dict[str, Any] = Field(
262259
description=(
263260
"Any additional information or metadata that was passed for this benchmark."
264261
)
@@ -292,9 +289,9 @@ class BenchmarkAggregator(
292289
default_factory=RequestsRunningStats,
293290
)
294291
results: StatusBreakdown[
295-
List[SchedulerRequestResult[RequestT, ResponseT]],
296-
List[SchedulerRequestResult[RequestT, ResponseT]],
297-
List[SchedulerRequestResult[RequestT, ResponseT]],
292+
list[SchedulerRequestResult[RequestT, ResponseT]],
293+
list[SchedulerRequestResult[RequestT, ResponseT]],
294+
list[SchedulerRequestResult[RequestT, ResponseT]],
298295
None,
299296
] = Field(
300297
description=(
@@ -516,7 +513,7 @@ class GenerativeBenchmarkAggregator(
516513
"avaiable that match the preferred source."
517514
)
518515
)
519-
processor_args: Optional[Dict[str, Any]] = Field(
516+
processor_args: Optional[dict[str, Any]] = Field(
520517
description=(
521518
"Additional arguments to pass to the tokenizer if it requires "
522519
"any specific configuration for loading or processing."
@@ -636,12 +633,12 @@ def compile(self) -> GenerativeBenchmark:
636633

637634
def _compile_results(
638635
self,
639-
) -> Tuple[
640-
List[GenerativeTextResponseStats],
641-
List[GenerativeTextErrorStats],
642-
List[GenerativeTextErrorStats],
636+
) -> tuple[
637+
list[GenerativeTextResponseStats],
638+
list[GenerativeTextErrorStats],
639+
list[GenerativeTextErrorStats],
643640
]:
644-
successful: List[GenerativeTextResponseStats] = [
641+
successful: list[GenerativeTextResponseStats] = [
645642
GenerativeTextResponseStats(
646643
request_id=result.request.request_id,
647644
request_type=result.request.request_type,
@@ -670,7 +667,7 @@ def _compile_results(
670667
for result in self.results.successful
671668
if result.request and result.response
672669
]
673-
incomplete: List[GenerativeTextErrorStats] = [
670+
incomplete: list[GenerativeTextErrorStats] = [
674671
GenerativeTextErrorStats(
675672
error=result.response.error or "",
676673
request_id=result.request.request_id,
@@ -700,7 +697,7 @@ def _compile_results(
700697
for result in self.results.incomplete
701698
if result.request and result.response
702699
]
703-
error: List[GenerativeTextErrorStats] = [
700+
error: list[GenerativeTextErrorStats] = [
704701
GenerativeTextErrorStats(
705702
error=result.response.error or "",
706703
request_id=result.request.request_id,

src/guidellm/benchmark/benchmark.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import random
22
import uuid
3-
from typing import Any, Dict, List, Literal, Optional, TypeVar, Union
3+
from typing import Any, Literal, Optional, TypeVar, Union
44

55
from pydantic import Field, computed_field
66

@@ -273,7 +273,7 @@ class Benchmark(StandardBaseModel):
273273
"requests for this benchmark."
274274
),
275275
)
276-
extras: Dict[str, Any] = Field(
276+
extras: dict[str, Any] = Field(
277277
description=(
278278
"Any additional information or metadata that was passed for this benchmark."
279279
)
@@ -608,9 +608,9 @@ def duration(self) -> float:
608608
default=None,
609609
)
610610
requests: StatusBreakdown[
611-
List[GenerativeTextResponseStats],
612-
List[GenerativeTextErrorStats],
613-
List[GenerativeTextErrorStats],
611+
list[GenerativeTextResponseStats],
612+
list[GenerativeTextErrorStats],
613+
list[GenerativeTextErrorStats],
614614
None,
615615
] = Field(
616616
description=(
@@ -663,14 +663,14 @@ def set_sample_size(self, sample_size: Optional[int]) -> "GenerativeBenchmark":
663663
@staticmethod
664664
def from_stats(
665665
run_id: str,
666-
successful: List[GenerativeTextResponseStats],
667-
incomplete: List[GenerativeTextErrorStats],
668-
errored: List[GenerativeTextErrorStats],
666+
successful: list[GenerativeTextResponseStats],
667+
incomplete: list[GenerativeTextErrorStats],
668+
errored: list[GenerativeTextErrorStats],
669669
args: BenchmarkArgs,
670670
run_stats: BenchmarkRunStats,
671671
worker: GenerativeRequestsWorkerDescription,
672672
requests_loader: GenerativeRequestLoaderDescription,
673-
extras: Optional[Dict[str, Any]],
673+
extras: Optional[dict[str, Any]],
674674
) -> "GenerativeBenchmark":
675675
"""
676676
Create a GenerativeBenchmark instance from the given statistics and metadata.
@@ -696,7 +696,7 @@ def from_stats(
696696
populated and calculated
697697
"""
698698
total = successful + incomplete + errored
699-
total_types: List[Literal["successful", "incomplete", "error"]] = [
699+
total_types: list[Literal["successful", "incomplete", "error"]] = [
700700
*["successful"] * len(successful), # type: ignore[list-item]
701701
*["incomplete"] * len(incomplete), # type: ignore[list-item]
702702
*["error"] * len(errored), # type: ignore[list-item]

src/guidellm/benchmark/benchmarker.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import time
22
import uuid
33
from abc import ABC, abstractmethod
4+
from collections.abc import AsyncGenerator, Iterable
45
from pathlib import Path
56
from typing import (
67
Any,
7-
AsyncGenerator,
8-
Dict,
98
Generic,
10-
Iterable,
119
Literal,
1210
Optional,
1311
Union,
@@ -136,7 +134,7 @@ def __init__(
136134
worker: RequestsWorker[RequestT, ResponseT],
137135
request_loader: Iterable[RequestT],
138136
requests_loader_description: RequestLoaderDescription,
139-
benchmark_save_extras: Optional[Dict[str, Any]] = None,
137+
benchmark_save_extras: Optional[dict[str, Any]] = None,
140138
):
141139
self.worker = worker
142140
self.scheduler: Scheduler[RequestT, ResponseT] = Scheduler(
@@ -294,9 +292,9 @@ def __init__(
294292
backend: Backend,
295293
request_loader: Iterable[GenerationRequest],
296294
request_loader_description: GenerativeRequestLoaderDescription,
297-
benchmark_save_extras: Optional[Dict[str, Any]] = None,
295+
benchmark_save_extras: Optional[dict[str, Any]] = None,
298296
processor: Optional[Union[str, Path, PreTrainedTokenizerBase]] = None,
299-
processor_args: Optional[Dict[str, Any]] = None,
297+
processor_args: Optional[dict[str, Any]] = None,
300298
):
301299
super().__init__(
302300
worker=GenerativeRequestsWorker(backend),

0 commit comments

Comments
 (0)