2121from setuptools .command .develop import develop as _develop
2222
2323
24+ class BuildGenerateProtos (setuptools .Command ):
25+ def run (self ):
26+ self .run_command ('generate_proto' )
27+ return super ().run ()
28+
29+
30+ class GenerateProtosCommand (setuptools .Command ):
31+ """Command to run prototagandcopy.py script."""
32+ user_options = []
33+
34+ def initialize_options (self ):
35+ pass
36+
37+ def finalize_options (self ):
38+ pass
39+
40+ def run (self ):
41+ import subprocess # pylint: disable=import-outside-toplevel
42+ import os
43+ from pathlib import Path
44+
45+ # Check if we're in an sdist build (proto files should already exist)
46+ proto_files_exist = any (Path ('.' ).glob ('**/*_pb2.py' ))
47+ proto_dir_exists = Path ("../submodules/kuksa-proto/proto/" ).exists ()
48+
49+ if proto_files_exist :
50+ print ("Proto files already exist, skipping package tagging" )
51+ # List files in the current directory
52+ print ("Existing proto files:" )
53+ for file in Path ('.' ).glob ('**/*_pb2.py' ):
54+ print (f" - { file } " )
55+ return
56+
57+ if not proto_dir_exists :
58+ print ("Warning: Proto directory not found, skipping package tagging" )
59+ return
60+
61+ print (f"Generating package from proto: { os .getcwd ()} " )
62+ result = subprocess .call (['python' , 'prototagandcopy.py' ])
63+ if result != 0 :
64+ print (f"Warning: prototagandcopy.py failed with exit code { result } " )
65+ # print("This is how it looks like:")
66+ # for file in Path('./kuksa').glob('**/*'):
67+ # print(f" - {file}")
68+
69+
2470class BuildPackageProtos (setuptools .Command ):
2571 def run (self ):
2672 self .run_command ('build_pb2' )
@@ -37,32 +83,110 @@ def finalize_options(self):
3783 pass
3884
3985 def run (self ):
40- from grpc_tools import command # pylint: disable=import-outside-toplevel
86+ import subprocess
87+ import sys
88+ from pathlib import Path
89+
90+ # Check if proto files already exist (generated by previous step)
91+ proto_files_exist = any (Path ('.' ).glob ('**/*_pb2.py' ))
92+ if proto_files_exist :
93+ print ("Proto files already exist, skipping protobuf compilation" )
94+ # Recursively list every file in folder "kuksa"
95+ for file in Path ('./kuksa' ).glob ('**/*' ):
96+ print (f" - { file } " )
97+ return
98+
99+ # Check if we have .proto files to compile
100+ proto_source_files = list (Path ('.' ).glob ('**/*.proto' ))
101+ if not proto_source_files :
102+ print ("No .proto files found, skipping protobuf compilation" )
103+ return
104+
105+ print (f"Found { len (proto_source_files )} .proto files to compile" )
106+
107+ try :
108+ from grpc_tools import command
109+ print ("Compiling protobuf files..." )
110+ command .build_package_protos ("." , strict_mode = True )
111+ except ImportError :
112+ # Fallback to direct protoc call
113+ print ("grpc_tools not found, using protoc directly." )
114+ if proto_source_files :
115+ subprocess .check_call ([
116+ sys .executable , "-m" , "grpc_tools.protoc" ,
117+ "--proto_path=." ,
118+ "--python_out=." ,
119+ "--grpc_python_out=." ,
120+ * [str (f ) for f in proto_source_files ]
121+ ])
122+
123+
124+ class BuildCommand (BuildGenerateProtos , BuildPackageProtos , build .build ):
125+ ...
41126
42- command .build_package_protos ("." , strict_mode = True )
43127
128+ class BuildPyCommand (BuildGenerateProtos , BuildPackageProtos , build_py .build_py ): # pylint: disable=too-many-ancestors
129+ def finalize_options (self ):
130+ # First run the parent finalize_options which includes proto generation
131+ super ().finalize_options ()
44132
45- class BuildCommand (BuildPackageProtos , build .build ):
46- ...
133+ # After proto generation, ensure packages are properly set BEFORE build_py runs
134+ self .ensure_proto_packages ()
135+
136+ def run (self ):
137+ # Just run the normal build_py
138+ build_py .build_py .run (self )
47139
140+ def ensure_proto_packages (self ):
141+ """Ensure generated proto packages are included in the distribution."""
142+ import os
48143
49- class BuildPyCommand (BuildPackageProtos , build_py .build_py ): # pylint: disable=too-many-ancestors
50- ...
144+ # Find all proto packages
145+ print ("Searching and adding dynamically built proto packages..." )
146+ proto_packages = []
147+
148+ for root , dirs , files in os .walk ('.' ):
149+ if '__init__.py' in files :
150+ package = root .replace ('./' , '' ).replace ('/' , '.' ).lstrip ('.' )
151+ print (f"Found package: { package } " )
152+ if package and any (proto_name in package for proto_name in ['kuksa' , 'sdv' ]):
153+ # Skip build directories
154+ if not package .startswith ('build.' ):
155+ proto_packages .append (package )
156+ print (f"Adding proto package: { package } " )
157+
158+ # Get current packages from distribution or setup.cfg
159+ current_packages = []
160+ if hasattr (self .distribution , 'packages' ) and self .distribution .packages :
161+ current_packages = list (self .distribution .packages )
162+
163+ # Add proto packages
164+ all_packages = current_packages + [pkg for pkg in proto_packages if pkg not in current_packages ]
165+
166+ # Update the distribution packages
167+ self .distribution .packages = all_packages
168+ print (f"Final package list: { all_packages } " )
51169
52170
53- class SDistCommand (BuildPackageProtos , sdist .sdist ):
171+ class SDistCommand (BuildGenerateProtos , BuildPackageProtos , sdist .sdist ):
54172 ...
55173
56174
57- class DevelopCommand (BuildPackageProtos , _develop ):
175+ class DevelopCommand (BuildGenerateProtos , BuildPackageProtos , _develop ):
58176
59177 def run (self ):
60- self .run_command ("build_pb2" )
178+ try :
179+ self .run_command ("generate_proto" )
180+ self .run_command ("build_pb2" )
181+ except Exception as e :
182+ print (f"Warning: Proto generation failed: { e } " )
183+ print ("Continuing with development install..." )
61184 super ().run ()
62185
63186
64187setuptools .setup (
65188 cmdclass = {
189+ "generate_proto" : GenerateProtosCommand ,
66190 "build" : BuildCommand ,
67191 "build_pb2" : BuildPackageProtosCommand ,
68192 "build_py" : BuildPyCommand , # Used for editable installs but also for building wheels
0 commit comments