forked from sgl-project/sglang
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.py
More file actions
125 lines (94 loc) · 3.82 KB
/
setup.py
File metadata and controls
125 lines (94 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""
Custom setup.py for SGLang that compiles protobuf files during build.
This file works alongside pyproject.toml. It hooks into the build process
to automatically generate gRPC/protobuf Python files from .proto sources
when building the wheel or doing editable installs.
"""
import os
from pathlib import Path
from setuptools import setup
from setuptools.command.build_py import build_py
from setuptools.command.develop import develop
from setuptools.command.egg_info import egg_info
from setuptools.errors import SetupError
PROTO_SOURCE = "sglang/srt/grpc/sglang_scheduler.proto"
def compile_proto():
"""Compile the protobuf file to Python using grpc_tools.protoc."""
proto_path = Path(__file__).parent / PROTO_SOURCE
if not proto_path.exists():
print(f"Warning: Proto file not found at {proto_path}, skipping generation")
return
print(f"Generating gRPC files from {PROTO_SOURCE}")
output_dir = proto_path.parent
proto_dir = proto_path.parent
# Import grpc_tools.protoc directly instead of running as subprocess.
# This ensures we use the grpcio-tools installed in the build environment,
# since sys.executable may point to the main Python interpreter in
# pip's isolated build environments.
try:
import grpc_tools
from grpc_tools import protoc
except ImportError as e:
raise SetupError(
f"Failed to import grpc_tools: {e}. "
"Ensure grpcio-tools is listed in build-system.requires in pyproject.toml"
)
# Get the path to well-known proto files bundled with grpcio-tools
# (e.g., google/protobuf/timestamp.proto, google/protobuf/struct.proto)
grpc_tools_proto_path = Path(grpc_tools.__file__).parent / "_proto"
# Build the protoc arguments (protoc.main expects argv-style list)
args = [
"protoc", # argv[0] is the program name
f"-I{proto_dir}",
f"-I{grpc_tools_proto_path}", # Include path for well-known protos
f"--python_out={output_dir}",
f"--grpc_python_out={output_dir}",
f"--pyi_out={output_dir}",
str(proto_dir / proto_path.name),
]
print(f"Running protoc with args: {args[1:]}")
# Save and restore cwd since protoc may change it
original_cwd = os.getcwd()
try:
result = protoc.main(args)
if result != 0:
raise SetupError(f"protoc failed with exit code {result}")
finally:
os.chdir(original_cwd)
# Fix imports in generated grpc file (change absolute to relative imports)
_fix_imports(output_dir, proto_path.stem)
print(f"Successfully generated gRPC files in {output_dir}")
def _fix_imports(output_dir: Path, proto_stem: str):
"""Fix imports in generated files to use relative imports."""
grpc_file = output_dir / f"{proto_stem}_pb2_grpc.py"
if grpc_file.exists():
content = grpc_file.read_text()
# Change absolute import to relative import
old_import = f"import {proto_stem}_pb2"
new_import = f"from . import {proto_stem}_pb2"
if old_import in content:
content = content.replace(old_import, new_import)
grpc_file.write_text(content)
print("Fixed imports in generated gRPC file")
class BuildPyWithProto(build_py):
"""Build Python modules, generating gRPC files from .proto sources first."""
def run(self):
compile_proto()
super().run()
class DevelopWithProto(develop):
"""Editable install with gRPC file generation."""
def run(self):
compile_proto()
super().run()
class EggInfoWithProto(egg_info):
"""Egg info generation with gRPC file generation."""
def run(self):
compile_proto()
super().run()
setup(
cmdclass={
"build_py": BuildPyWithProto,
"develop": DevelopWithProto,
"egg_info": EggInfoWithProto,
},
)