Skip to content

Commit f68cc04

Browse files
committed
chore: improve pip build tool detection
Signed-off-by: behnazh-w <behnaz.hassanshahi@oracle.com>
1 parent ff4fc6a commit f68cc04

File tree

16 files changed

+261
-117
lines changed

16 files changed

+261
-117
lines changed

docs/source/pages/tutorials/rebuild_third_party_artifacts.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ By default we generate the buildspec in JSON format as follows:
120120
"ecosystem": "maven",
121121
"purl": "pkg:maven/org.apache.hugegraph/computer-k8s@1.0.0",
122122
"language": "java",
123-
"build_tool": "maven",
123+
"build_tools": [
124+
"maven"
125+
],
124126
"build_commands": [
125127
[
126128
"mvn",

src/macaron/build_spec_generator/common_spec/base_spec.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ class BaseBuildSpecDict(TypedDict, total=False):
2525
#: The programming language, e.g., 'java', 'python', 'javascript'.
2626
language: Required[str]
2727

28-
#: The build tool or package manager, e.g., 'maven', 'gradle', 'pip', 'poetry', 'npm', 'yarn'.
29-
build_tool: Required[str]
28+
#: The build tools or package managers, e.g., 'maven', 'gradle', 'pip', 'poetry', 'npm', 'yarn'.
29+
build_tools: Required[list[str]]
3030

3131
#: The version of Macaron used for generating the spec.
3232
macaron_version: Required[str]
@@ -94,21 +94,21 @@ def resolve_fields(self, purl: PackageURL) -> None:
9494
"""
9595

9696
@abstractmethod
97-
def get_default_build_command(
97+
def get_default_build_commands(
9898
self,
99-
build_tool_name: str,
100-
) -> list[str]:
101-
"""Return a default build command for the build tool.
99+
build_tool_names: list[str],
100+
) -> list[list[str]]:
101+
"""Return the default build commands for the build tools.
102102
103103
Parameters
104104
----------
105-
build_tool_name: str
106-
The build tool to get the default build command.
105+
build_tool_names: list[str]
106+
The build tools to get the default build command.
107107
108108
Returns
109109
-------
110-
list[str]
111-
The build command as a list[str].
110+
list[list[str]]
111+
The build command as a list[list[str]].
112112
113113
Raises
114114
------

src/macaron/build_spec_generator/common_spec/core.py

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,14 @@ def compose_shell_commands(cmds_sequence: list[list[str]]) -> str:
120120
return result
121121

122122

123-
def get_macaron_build_tool_name(
123+
def get_macaron_build_tool_names(
124124
build_tool_facts: Sequence[BuildToolFacts], target_language: str
125-
) -> MacaronBuildToolName | None:
125+
) -> list[MacaronBuildToolName] | None:
126126
"""
127-
Retrieve the Macaron build tool name for supported projects from the database facts.
127+
Retrieve the Macaron build tool names for supported projects from the database facts.
128128
129-
Iterates over the provided build tool facts and returns the first valid `MacaronBuildToolName`
130-
for a supported language. If no valid build tool name is found, returns None.
131-
132-
.. note::
133-
If multiple build tools are present in the database, only the first valid one encountered
134-
in the sequence is returned.
129+
Iterates over the provided build tool facts and returns the list of valid `MacaronBuildToolName`
130+
for a supported language.
135131
136132
Parameters
137133
----------
@@ -142,31 +138,27 @@ def get_macaron_build_tool_name(
142138
143139
Returns
144140
-------
145-
MacaronBuildToolName or None
146-
The corresponding Macaron build tool name if found, otherwise None.
141+
list[MacaronBuildToolName]
142+
The corresponding Macaron build tool names.
147143
"""
144+
build_tool_names = []
148145
for fact in build_tool_facts:
149146
if fact.language.lower() == target_language:
150147
try:
151-
macaron_build_tool_name = MacaronBuildToolName(fact.build_tool_name)
148+
build_tool_names.append(MacaronBuildToolName(fact.build_tool_name))
152149
except ValueError:
153150
continue
154151

155-
# TODO: What happen if we report multiple build tools in the database?
156-
return macaron_build_tool_name
157-
158-
return None
152+
return build_tool_names
159153

160154

161-
def get_build_tool_name(
155+
def get_build_tool_names(
162156
component_id: int, session: sqlalchemy.orm.Session, target_language: str
163-
) -> MacaronBuildToolName | None:
164-
"""
165-
Retrieve the Macaron build tool name for a given component.
157+
) -> list[MacaronBuildToolName] | None:
158+
"""Retrieve the Macaron build tool names for a given component.
166159
167-
Queries the database for build tool facts associated with the specified component ID
168-
and returns the corresponding `MacaronBuildToolName` if found. If no valid build tool
169-
information is available or an error occurs during the query, returns None.
160+
Queries the database for build tool facts associated with the specified component ID.
161+
It returns the corresponding list of `MacaronBuildToolName` if found.
170162
171163
Parameters
172164
----------
@@ -179,7 +171,7 @@ def get_build_tool_name(
179171
180172
Returns
181173
-------
182-
MacaronBuildToolName or None
174+
list[MacaronBuildToolName] | None
183175
The corresponding build tool name for the component if available, otherwise None.
184176
"""
185177
try:
@@ -206,7 +198,7 @@ def get_build_tool_name(
206198
[(fact.build_tool_name, fact.language) for fact in build_tool_facts],
207199
)
208200

209-
return get_macaron_build_tool_name(build_tool_facts, target_language)
201+
return get_macaron_build_tool_names(build_tool_facts, target_language)
210202

211203

212204
def get_build_command_info(
@@ -348,10 +340,10 @@ def gen_generic_build_spec(
348340
latest_component_repository.commit_sha,
349341
)
350342

351-
build_tool_name = get_build_tool_name(
343+
build_tool_names = get_build_tool_names(
352344
component_id=latest_component.id, session=session, target_language=target_language
353345
)
354-
if not build_tool_name:
346+
if not build_tool_names:
355347
raise GenerateBuildSpecError(f"Failed to determine build tool for {purl}.")
356348

357349
build_command_info = get_build_command_info(
@@ -380,7 +372,7 @@ def gen_generic_build_spec(
380372
"ecosystem": purl.type,
381373
"purl": str(purl),
382374
"language": target_language,
383-
"build_tool": build_tool_name.value,
375+
"build_tools": [build_tool.value for build_tool in build_tool_names],
384376
"build_commands": [selected_build_command],
385377
}
386378
)

src/macaron/build_spec_generator/common_spec/maven_spec.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,47 @@ def __init__(self, data: BaseBuildSpecDict):
3131
"""
3232
self.data = data
3333

34-
def get_default_build_command(
34+
def get_default_build_commands(
3535
self,
36-
build_tool_name: str,
37-
) -> list[str]:
38-
"""Return a default build command for the build tool.
36+
build_tool_names: list[str],
37+
) -> list[list[str]]:
38+
"""Return the default build commands for the build tools.
3939
4040
Parameters
4141
----------
42-
build_tool_name: str
43-
The build tool to get the default build command.
42+
build_tool_names: list[str]
43+
The build tools to get the default build command.
4444
4545
Returns
4646
-------
47-
list[str]
48-
The build command as a list[str].
47+
list[list[str]]
48+
The build command as a list[list[str]].
4949
5050
Raises
5151
------
5252
GenerateBuildSpecError
5353
If there is no default build command available for the specified build tool.
5454
"""
55-
default_build_command = None
55+
default_build_commands = []
5656

57-
match build_tool_name:
58-
case "maven":
59-
default_build_command = "mvn clean package".split()
60-
case "gradle":
61-
default_build_command = "./gradlew clean assemble publishToMavenLocal".split()
62-
case _:
63-
pass
57+
for build_tool_name in build_tool_names:
6458

65-
if not default_build_command:
59+
match build_tool_name:
60+
case "maven":
61+
default_build_commands.append("mvn clean package".split())
62+
case "gradle":
63+
default_build_commands.append("./gradlew clean assemble publishToMavenLocal".split())
64+
case _:
65+
pass
66+
67+
if not default_build_commands:
6668
logger.critical(
67-
"There is no default build command available for the build tool %s.",
68-
build_tool_name,
69+
"There is no default build command available for the build tools %s.",
70+
build_tool_names,
6971
)
7072
raise GenerateBuildSpecError("Unable to find a default build command.")
7173

72-
return default_build_command
74+
return default_build_commands
7375

7476
def resolve_fields(self, purl: PackageURL) -> None:
7577
"""
@@ -113,9 +115,9 @@ def resolve_fields(self, purl: PackageURL) -> None:
113115
self.data["language_version"] = [major_jdk_version]
114116

115117
# Resolve and patch build commands.
116-
selected_build_commands = self.data["build_commands"] or [
117-
self.get_default_build_command(self.data["build_tool"])
118-
]
118+
selected_build_commands = self.data["build_commands"] or self.get_default_build_commands(
119+
self.data["build_tools"]
120+
)
119121

120122
patched_build_commands = patch_commands(
121123
cmds_sequence=selected_build_commands,

src/macaron/build_spec_generator/common_spec/pypi_spec.py

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,51 +39,53 @@ def __init__(self, data: BaseBuildSpecDict):
3939
"""
4040
self.data = data
4141

42-
def get_default_build_command(
42+
def get_default_build_commands(
4343
self,
44-
build_tool_name: str,
45-
) -> list[str]:
46-
"""Return a default build command for the build tool.
44+
build_tool_names: list[str],
45+
) -> list[list[str]]:
46+
"""Return the default build commands for the build tools.
4747
4848
Parameters
4949
----------
50-
build_tool_name: str
51-
The build tool to get the default build command.
50+
build_tool_names: list[str]
51+
The build tools to get the default build command.
5252
5353
Returns
5454
-------
55-
list[str]
56-
The build command as a list[str].
55+
list[list[str]]
56+
The build command as a list[list[str]].
5757
5858
Raises
5959
------
6060
GenerateBuildSpecError
6161
If there is no default build command available for the specified build tool.
6262
"""
63-
default_build_command = None
64-
65-
match build_tool_name:
66-
case "pip":
67-
default_build_command = "python -m build".split()
68-
case "poetry":
69-
default_build_command = "poetry build".split()
70-
case "flit":
71-
default_build_command = "flit build".split()
72-
case "hatch":
73-
default_build_command = "hatch build".split()
74-
case "conda":
75-
default_build_command = "conda build".split()
76-
case _:
77-
pass
78-
79-
if not default_build_command:
63+
default_build_commands = []
64+
65+
for build_tool_name in build_tool_names:
66+
67+
match build_tool_name:
68+
case "pip":
69+
default_build_commands.append("python -m build".split())
70+
case "poetry":
71+
default_build_commands.append("poetry build".split())
72+
case "flit":
73+
default_build_commands.append("flit build".split())
74+
case "hatch":
75+
default_build_commands.append("hatch build".split())
76+
case "conda":
77+
default_build_commands.append("conda build".split())
78+
case _:
79+
pass
80+
81+
if not default_build_commands:
8082
logger.critical(
81-
"There is no default build command available for the build tool %s.",
82-
build_tool_name,
83+
"There is no default build command available for the build tools %s.",
84+
build_tool_names,
8385
)
8486
raise GenerateBuildSpecError("Unable to find a default build command.")
8587

86-
return default_build_command
88+
return default_build_commands
8789

8890
def resolve_fields(self, purl: PackageURL) -> None:
8991
"""
@@ -202,13 +204,14 @@ def resolve_fields(self, purl: PackageURL) -> None:
202204

203205
# Use the default build command for pure Python packages.
204206
if "any" in wheel_name_platforms:
205-
patched_build_commands = [self.get_default_build_command(self.data["build_tool"])]
207+
patched_build_commands = self.get_default_build_commands(self.data["build_tools"])
206208

207209
if not patched_build_commands:
208210
# Resolve and patch build commands.
209-
selected_build_commands = self.data["build_commands"] or [
210-
self.get_default_build_command(self.data["build_tool"])
211-
]
211+
selected_build_commands = self.data["build_commands"] or self.get_default_build_commands(
212+
self.data["build_tools"]
213+
)
214+
212215
patched_build_commands = (
213216
patch_commands(
214217
cmds_sequence=selected_build_commands,

src/macaron/build_spec_generator/reproducible_central/reproducible_central.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ def gen_reproducible_central_build_spec(build_spec: BaseBuildSpecDict) -> str |
7777
GenerateBuildSpecError
7878
Raised if generation of the build spec fails.
7979
"""
80-
if build_spec["build_tool"].upper() not in (e.name for e in ReproducibleCentralBuildTool):
80+
if build_spec["build_tools"][0].upper() not in (e.name for e in ReproducibleCentralBuildTool):
8181
raise GenerateBuildSpecError(
82-
f"Build tool {build_spec['build_tool']} is not supported by Reproducible Central. "
82+
f"Build tool {build_spec['build_tools'][0]} is not supported by Reproducible Central. "
8383
f"Supported build tools: {[build.name for build in ReproducibleCentralBuildTool]}"
8484
)
8585
if build_spec["group_id"] is None:
@@ -92,7 +92,7 @@ def gen_reproducible_central_build_spec(build_spec: BaseBuildSpecDict) -> str |
9292
"version": build_spec["version"],
9393
"git_repo": build_spec["git_repo"],
9494
"git_tag": build_spec["git_tag"],
95-
"tool": ReproducibleCentralBuildTool[build_spec["build_tool"].upper()].value,
95+
"tool": ReproducibleCentralBuildTool[build_spec["build_tools"][0].upper()].value,
9696
"newline": build_spec["newline"],
9797
"buildinfo": f"target/{build_spec['artifact_id']}-{build_spec['version']}.buildinfo",
9898
"jdk": build_spec["language_version"][0],

src/macaron/config/defaults.ini

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -290,16 +290,14 @@ build_configs =
290290
pyproject.toml
291291
packager =
292292
pip
293-
pip3
294-
flit
295-
conda
296-
hatch
293+
build
297294
publisher =
298295
twine
299-
flit
300-
conda
301-
tox
302-
hatch
296+
# build-system information.
297+
build_requires =
298+
setuptools
299+
build_backend =
300+
setuptools.build_meta
303301
# These are the Python interpreters that may be used to load modules.
304302
interpreter =
305303
python

0 commit comments

Comments
 (0)