Skip to content

Commit f905346

Browse files
parfeniukinkDmytro ParfeniukDaltheCow
authored
Code Quality (#10)
* `setup.py` is replaced with the `pyproject.toml`. More here: https://peps.python.org/pep-0621/ * Code Quality tool configurations are improved * Dependencies are grouped to be reused by other tools * All issues are resolved according to code quality requirements * The `tox` tool is added to the dependencies list to automate the code quality-checking process * Python versions that are tested: 3.8, 3.9, 3.10, 3.11, 3.12 * The `tox.ini` configuration file is created * Github Actions CI workflow is added * Integration tests are not added to the automation process. sLLM service in GithubActions TBD... * `flake8` linter is removed since the `ruff` is used * `README.md` now includes the *Code Quality* section with all the instructions and examples --------- Co-authored-by: Dmytro Parfeniuk <parfeniukinik@gmail.com> Co-authored-by: dalthecow <dalcowboiz@gmail.com>
1 parent ae61346 commit f905346

File tree

20 files changed

+329
-137
lines changed

20 files changed

+329
-137
lines changed

.github/workflows/ci.yml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,23 @@
1-
TODO
1+
name: Code Quality Check
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
8+
jobs:
9+
code_quality:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
16+
- name: Install dependencies
17+
run: |
18+
python -m pip install --upgrade pip
19+
pip install tox
20+
21+
- name: Run tox
22+
run: tox
23+

.github/workflows/release.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
TODO

Makefile

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,59 @@
11
.PHONY: install
22
install:
3-
python -m pip install -r requirements.txt
3+
python -m pip install .
4+
45

56
.PHONY: install.dev
67
install.dev:
78
python -m pip install -e .[dev]
89

10+
911
.PHONY: build
1012
build:
1113
python setup.py sdist bdist_wheel
1214

15+
.PHONY: style
16+
style:
17+
python -m ruff format src tests
18+
python -m isort src tests
19+
python -m flake8 src tests --max-line-length 88
20+
21+
22+
.PHONY: types
23+
types:
24+
python -m mypy --check-untyped-defs
25+
1326

1427
.PHONY: quality
1528
quality:
1629
python -m ruff check src tests
30+
python -m black --check src tests
1731
python -m isort --check src tests
18-
python -m flake8 src tests --max-line-length 88
19-
python -m mypy src
32+
python -m mypy --check-untyped-defs
2033

2134

22-
.PHONY: style
23-
style:
24-
python -m ruff format src tests
25-
python -m isort src tests
26-
python -m flake8 src tests --max-line-length 88
27-
2835

2936
.PHONY: test
3037
test:
3138
python -m pytest -s -vvv --cache-clear tests
3239

40+
3341
.PHONY: test.unit
3442
test.unit:
3543
python -m pytest tests/unit
3644

45+
3746
.PHONY: test.integration
3847
test.integration:
3948
python -m pytest tests/integration
4049

50+
4151
.PHONY: test.e2e
4252
test.e2e:
4353
python -m pytest tests/e2e
4454

4555

56+
4657
.PHONY: clean
4758
clean:
4859
rm -rf build
@@ -52,3 +63,4 @@ clean:
5263
find . -type d -name "__pycache__" -exec rm -r {} +
5364
rm -rf .mypy_cache
5465
rm -rf .pytest_cache
66+
rm -rf .tox

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,53 @@ set -o allexport; source .env; set +o allexport
1818
| --------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1919
| OPENAI_BASE_URL | http://127.0.0.1:8080 | The host where the `openai` library will make requests to. For running integration tests it is required to have the external OpenAI compatible server running. |
2020
| OPENAI_API_KEY | invalid | [OpenAI Platform](https://platform.openai.com/api-keys) to create a new API key. This value is not used for tests. |
21+
22+
</br>
23+
24+
# Code Quality
25+
26+
The variety of tools are available for checking the code quality.
27+
28+
All the code quality tools configuration is placed into next files: `pyproject.toml`, `Makefile`, `tox.ini`
29+
30+
**To provide the code quality next tools are used:**
31+
32+
- `pytest` as a testing framework
33+
- `ruff` as a linter
34+
- `black` & `isort` as formatters
35+
- `mypy` as a static type checker
36+
- `tox` as a automation tool
37+
- `make` as a automation tool (works only on Unix by default)
38+
39+
**Checking code quality using CLI**
40+
41+
All the tools could be run right from the CLI.
42+
43+
Recommended command template: `python -m pytest test.integration`
44+
45+
46+
**Checking code quality using Makefile**
47+
48+
Using `Makefile` you can run almost all common scripts to check the code quality, install dependencies, and to provide auto fixes. All the commands from the `Makefile` are valid to be used in the CLI.
49+
50+
Here are some commands
51+
52+
```sh
53+
# install dev dependencies
54+
make install.dev
55+
56+
# run unit tests
57+
make test.unit
58+
59+
# run quality checkers
60+
make quality
61+
62+
# run autofixes
63+
make style
64+
```
65+
66+
**Checking code quality using tox**
67+
68+
The `tox` is an automation tool for running code quality checkers for selected Python versions. The configuration is placed in the `tox.ini`.
69+
70+
To run the automation just run: `python -m tox`

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
TODO
1+
TODO

pyproject.toml

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,96 @@
22
requires = ["setuptools", "wheel"]
33
build-backend = "setuptools.build_meta"
44

5+
6+
[tool.setuptools.packages.find]
7+
where = ["src"]
8+
include = ["*"]
9+
10+
[tool.setuptools.package-data]
11+
guidellm = ["*"]
12+
13+
14+
# ************************************************
15+
# ********** Project Metadata **********
16+
# ************************************************
17+
18+
[project]
19+
name = "guidellm"
20+
version = "0.1.0"
21+
description = "Guidance platform for deploying and managing large language models."
22+
readme = { file = "README.md", content-type = "text/markdown" }
23+
requires-python = ">=3.8.0,<4.0"
24+
license = { file = "LICENSE" }
25+
authors = [ { name = "Neuralmagic, Inc." } ]
26+
urls = { homepage = "https://github.com/neuralmagic/guidellm" }
27+
dependencies = [
28+
"click",
29+
"datasets",
30+
"loguru",
31+
"numpy",
32+
"openai",
33+
"requests",
34+
"transformers",
35+
]
36+
37+
[project.optional-dependencies]
38+
dev = [
39+
"guidellm[code_quality]",
40+
"pre-commit",
41+
"sphinx",
42+
]
43+
code_quality = [
44+
"black",
45+
"isort",
46+
"mypy",
47+
"pytest",
48+
"pytest-mock",
49+
"ruff",
50+
"tox",
51+
"types-requests"
52+
]
53+
54+
55+
[project.entry-points.console_scripts]
56+
guidellm = "guidellm.main:main"
57+
58+
59+
# ************************************************
60+
# ********** Code Quality Tools **********
61+
# ************************************************
62+
563
[tool.black]
664
line-length = 88
765
target-version = ['py38']
866

67+
968
[tool.isort]
1069
profile = "black"
1170

71+
1272
[tool.mypy]
1373
files = "src/guidellm"
74+
python_version = '3.8'
75+
warn_redundant_casts = true
76+
warn_unused_ignores = true
77+
show_error_codes = true
78+
namespace_packages = true
79+
exclude = ["venv", ".tox"]
80+
81+
# Silint "type import errors" as our 3rd-party libs does not have types
82+
# Check: https://mypy.readthedocs.io/en/latest/config_file.html#import-discovery
83+
follow_imports = 'silent'
84+
85+
[[tool.mypy.overrides]]
86+
module = ["transformers.*", "datasets.*"]
87+
ignore_missing_imports=true
88+
1489

1590
[tool.ruff]
91+
line-length = 88
1692
exclude = ["build", "dist", "env", ".venv"]
1793
lint.select = ["E", "F", "W"]
1894

19-
[tool.flake8]
20-
max-line-length = 88
2195

2296
[tool.pytest.ini_options]
2397
addopts = '-s -vvv --cache-clear'
@@ -27,4 +101,3 @@ markers = [
27101
"sanity: detailed tests to ensure major functions work correctly",
28102
"regression: tests to ensure that new changes do not break existing functionality"
29103
]
30-

setup.py

Lines changed: 0 additions & 64 deletions
This file was deleted.

src/guidellm/backend/base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from abc import ABC, abstractmethod
22
from dataclasses import dataclass
33
from enum import Enum
4-
from typing import Iterator, List, Optional, Type, Union
4+
from typing import Dict, Iterator, List, Optional, Type
55

66
from loguru import logger
77

@@ -41,7 +41,7 @@ class Backend(ABC):
4141
An abstract base class with template methods for generative AI backends.
4242
"""
4343

44-
_registry = {}
44+
_registry: Dict[BackendEngine, "Type[Backend]"] = {}
4545

4646
@classmethod
4747
def register(cls, backend_type: BackendEngine):
@@ -59,7 +59,7 @@ def inner_wrapper(wrapped_class: Type["Backend"]):
5959
return inner_wrapper
6060

6161
@classmethod
62-
def create(cls, backend_type: Union[str, BackendEngine], **kwargs) -> "Backend":
62+
def create(cls, backend_type: BackendEngine, **kwargs) -> "Backend":
6363
"""
6464
Factory method to create a backend based on the backend type.
6565
@@ -77,7 +77,7 @@ def create(cls, backend_type: Union[str, BackendEngine], **kwargs) -> "Backend":
7777
logger.error(f"Unsupported backend type: {backend_type}")
7878
raise ValueError(f"Unsupported backend type: {backend_type}")
7979

80-
return cls._registry[backend_type](**kwargs)
80+
return Backend._registry[backend_type](**kwargs)
8181

8282
def submit(self, request: TextGenerationRequest) -> TextGenerationResult:
8383
"""
@@ -91,7 +91,7 @@ def submit(self, request: TextGenerationRequest) -> TextGenerationResult:
9191

9292
logger.info(f"Submitting request with prompt: {request.prompt}")
9393

94-
result = TextGenerationResult(request=request)
94+
result = TextGenerationResult(TextGenerationRequest(prompt=request.prompt))
9595
result.start(request.prompt)
9696

9797
for response in self.make_request(request): # GenerativeResponse

src/guidellm/backend/openai.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def available_models(self) -> List[str]:
130130
:rtype: List[str]
131131
"""
132132

133-
models: list[str] = [
133+
models: List[str] = [
134134
model.id for model in self.openai_client.models.list().data
135135
]
136136
logger.info(f"Available models: {models}")

0 commit comments

Comments
 (0)