1313import pathlib as _pathlib
1414import subprocess as _subprocess
1515import sys as _sys
16+ import tomllib as _tomllib
1617
1718import setuptools as _setuptools
18-
19- # The typing stub for this module is missing
20- import setuptools .command .build as _build_command # type: ignore[import]
19+ import setuptools .command .build as _build_command
2120
2221
2322class CompileProto (_setuptools .Command ):
@@ -58,16 +57,69 @@ class CompileProto(_setuptools.Command):
5857 ]
5958 """Options of the command."""
6059
60+ DEFAULT_OPTIONS : dict [str , str ] = {
61+ "proto_path" : "proto" ,
62+ "proto_glob" : "*.proto" ,
63+ "include_paths" : "submodules/api-common-protos,submodules/frequenz-api-common/proto" ,
64+ "py_path" : "py" ,
65+ }
66+
6167 def initialize_options (self ) -> None :
6268 """Initialize options."""
63- self .proto_path = "proto"
64- self .proto_glob = "*.proto"
65- self .include_paths = "submodules/api-common-protos"
66- self .py_path = "py"
69+ options = self ._get_options_from_pyproject_toml (self .DEFAULT_OPTIONS )
70+
71+ self .proto_path = options ["proto_path" ]
72+ self .proto_glob = options ["proto_glob" ]
73+ self .include_paths = options ["include_paths" ]
74+ self .py_path = options ["py_path" ]
6775
6876 def finalize_options (self ) -> None :
6977 """Finalize options."""
7078
79+ def _get_options_from_pyproject_toml (
80+ self , defaults : dict [str , str ]
81+ ) -> dict [str , str ]:
82+ """Get the options from the pyproject.toml file.
83+
84+ The options are read from the `[tool.frequenz-repo-config.setuptools.grpc_tools]`
85+ section of the pyproject.toml file.
86+
87+ Args:
88+ defaults: The default values for the options.
89+
90+ Returns:
91+ The options read from the pyproject.toml file.
92+ """
93+ try :
94+ with _pathlib .Path ("pyproject.toml" ).open ("rb" ) as toml_file :
95+ pyproject_toml = _tomllib .load (toml_file )
96+ except FileNotFoundError :
97+ return defaults
98+ except (IOError , OSError ) as err :
99+ print (f"WARNING: Failed to load pyproject.toml: { err } " )
100+ return defaults
101+
102+ try :
103+ config = pyproject_toml ["tool" ]["frequenz-repo-config" ]["setuptools" ][
104+ "grpc_tools"
105+ ]
106+ except KeyError :
107+ return defaults
108+
109+ known_keys = frozenset (defaults .keys ())
110+ config_keys = frozenset (config .keys ())
111+ if unknown_keys := config_keys - known_keys :
112+ print (
113+ "WARNING: There are some configuration keys in pyproject.toml we don't "
114+ "know about and will be ignored: "
115+ + ", " .join (f"'{ k } '" for k in unknown_keys )
116+ )
117+
118+ if "include_paths" in config :
119+ config ["include_paths" ] = "," .join (config ["include_paths" ])
120+
121+ return dict (defaults , ** {k : config [k ] for k in (known_keys & config_keys )})
122+
71123 def run (self ) -> None :
72124 """Compile the Python protobuf files."""
73125 include_paths = self .include_paths .split ("," )
@@ -76,7 +128,10 @@ def run(self) -> None:
76128 ]
77129
78130 if not proto_files :
79- print (f"No proto files found in { self .proto_path } /**/{ self .proto_glob } /" )
131+ print (
132+ f"No proto files found in { self .proto_path } /**/{ self .proto_glob } /, "
133+ "skipping compilation of proto files."
134+ )
80135 return
81136
82137 protoc_cmd = (
0 commit comments