Skip to content

Commit da944c6

Browse files
authored
Enable package mode for mgmt sdk (#42276)
* enable package mode for mgmt sdk * update classifier logic * fix ofr __init__.py * Update __init__.py * update * update * fix * Update swagger_to_sdk_config_autorest.json * update * fix for new service * fix for build * update * fix for judge tag
1 parent 07b029a commit da944c6

File tree

8 files changed

+98
-27
lines changed

8 files changed

+98
-27
lines changed

eng/tools/azure-sdk-tools/packaging_tools/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ def build_packaging(
5151
jenkins: bool = False,
5252
packages: List[str] = None,
5353
build_conf: bool = False,
54+
*,
55+
template_names: Optional[List[str]] = None,
5456
) -> None:
5557
package_names = set(packages) or set()
5658
if jenkins:
@@ -69,10 +71,12 @@ def build_packaging(
6971
raise ValueError("Was unable to find out the package names.")
7072

7173
for package_name in package_names:
72-
build_packaging_by_package_name(package_name, output_folder, build_conf)
74+
build_packaging_by_package_name(package_name, output_folder, build_conf, template_names)
7375

7476

75-
def build_packaging_by_package_name(package_name: str, output_folder: str, build_conf: bool = False) -> None:
77+
def build_packaging_by_package_name(
78+
package_name: str, output_folder: str, build_conf: bool = False, template_names: Optional[List[str]] = None
79+
) -> None:
7680
_LOGGER.info("Building template %s", package_name)
7781
package_folder = Path(output_folder) / Path(package_name)
7882

@@ -90,7 +94,11 @@ def build_packaging_by_package_name(package_name: str, output_folder: str, build
9094
env = Environment(loader=PackageLoader("packaging_tools", "templates/packaging_files"), keep_trailing_newline=True)
9195
conf = build_config(conf)
9296

97+
template_names = template_names or env.list_templates()
9398
for template_name in env.list_templates():
99+
if template_name not in template_names:
100+
_LOGGER.info("Skipping template %s", template_name)
101+
continue
94102
future_filepath = Path(output_folder) / package_name / template_name
95103

96104
# Might decide to make it more generic one day

eng/tools/azure-sdk-tools/packaging_tools/conf.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,19 @@ def read_conf(folder: Path) -> Dict[str, Any]:
4242

4343
def build_default_conf(folder: Path, package_name: str) -> None:
4444
conf_path = folder / CONF_NAME
45+
existing_conf = {_SECTION: {}}
4546
if conf_path.exists():
46-
_LOGGER.info("Skipping default conf since the file exists")
47-
return
47+
with open(conf_path, "rb") as fd:
48+
existing_conf = toml.load(fd)
49+
if _SECTION not in existing_conf:
50+
existing_conf[_SECTION] = {}
4851

4952
_LOGGER.info("Build default conf for %s", package_name)
50-
conf = {_SECTION: _CONFIG.copy()}
51-
conf[_SECTION]["package_name"] = package_name
52-
conf[_SECTION]["package_nspkg"] = package_name[: package_name.rindex("-")] + "-nspkg"
53+
for k in _CONFIG:
54+
if k not in existing_conf[_SECTION]:
55+
existing_conf[_SECTION][k] = _CONFIG[k]
56+
existing_conf[_SECTION]["package_name"] = package_name
57+
existing_conf[_SECTION]["package_nspkg"] = package_name[: package_name.rindex("-")] + "-nspkg"
5358

5459
with open(conf_path, "wb") as fd:
55-
tomlw.dump(conf, fd)
60+
tomlw.dump(existing_conf, fd)

eng/tools/azure-sdk-tools/packaging_tools/generate_utils.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def call_build_config(package_name: str, folder_name: str):
113113
os.environ.get("GH_TOKEN", None),
114114
packages=[package_name],
115115
build_conf=True,
116+
template_names=["README.md", "__init__.py"],
116117
)
117118
# Replace this check_call by in process equivalent call, for better debugging
118119
# check_call(
@@ -156,10 +157,19 @@ def generate_packaging_files(package_name, folder_name):
156157
sdk_packaging_toml.rename(pyproject_toml)
157158

158159
if "azure-mgmt-" in package_name:
160+
# if codegen generate pyproject.toml instead of setup.py, we delete existing setup.py
161+
setup_py = output_path / "setup.py"
162+
if setup_py.exists():
163+
_LOGGER.info(f"delete {setup_py} since codegen generate pyproject.toml")
164+
with open(pyproject_toml, "rb") as f:
165+
pyproject_content = toml.load(f)
166+
if pyproject_content.get("project"):
167+
setup_py.unlink()
168+
159169
call_build_config(package_name, folder_name)
160170
else:
161-
if not (output_path / CONF_NAME).exists():
162-
with open(output_path / CONF_NAME, "w") as file_out:
171+
if not pyproject_toml.exists():
172+
with open(pyproject_toml, "w") as file_out:
163173
file_out.write("[packaging]\nauto_update = false")
164174

165175
# add ci.yaml
@@ -243,7 +253,38 @@ def judge_tag_preview(path: str, package_name: str) -> bool:
243253
_LOGGER.info(f"can not open {file}")
244254
continue
245255

256+
skip_decorator_block = False
257+
decorator_depth = 0
258+
246259
for line in list_in:
260+
# skip the code of decorator @api_version_validation
261+
stripped_line = line.strip()
262+
263+
# Check if we're starting an @api_version_validation decorator block
264+
if "@api_version_validation" in stripped_line:
265+
skip_decorator_block = True
266+
decorator_depth = 0
267+
continue
268+
269+
# If we're in a decorator block, track parentheses depth
270+
if skip_decorator_block:
271+
decorator_depth += stripped_line.count("(") - stripped_line.count(")")
272+
# If we've closed all parentheses and hit a function definition, skip until next function/class
273+
if decorator_depth == 0 and (
274+
stripped_line.startswith("def ") or stripped_line.startswith("async def ")
275+
):
276+
continue
277+
# If we hit another decorator or function/class definition after closing parentheses, stop skipping
278+
if decorator_depth == 0 and (
279+
stripped_line.startswith("@")
280+
or stripped_line.startswith("def ")
281+
or stripped_line.startswith("async def ")
282+
or stripped_line.startswith("class ")
283+
):
284+
skip_decorator_block = False
285+
else:
286+
continue
287+
247288
if "DEFAULT_API_VERSION = " in line:
248289
default_api_version += line.split("=")[-1].strip("\n") # collect all default api version
249290
if default_api_version == "" and "api_version" in line and "method_added_on" not in line:
@@ -462,13 +503,11 @@ def gen_typespec(
462503
tsp_dir = (Path(spec_folder) / typespec_relative_path).resolve()
463504
repo_url = rest_repo_url.replace("https://github.com/", "")
464505
tspconfig = tsp_dir / "tspconfig.yaml"
465-
if tspconfig.exists():
506+
if tspconfig.exists() and api_version:
466507
with open(tspconfig, "r") as file_in:
467508
content = yaml.safe_load(file_in)
468509
if content.get("options", {}).get("@azure-tools/typespec-python"):
469-
content["options"]["@azure-tools/typespec-python"]["keep-setup-py"] = True
470-
if api_version:
471-
content["options"]["@azure-tools/typespec-python"]["api-version"] = api_version
510+
content["options"]["@azure-tools/typespec-python"]["api-version"] = api_version
472511
with open(tspconfig, "w") as file_out:
473512
yaml.dump(content, file_out)
474513
cmd = f"tsp-client init --tsp-config {tsp_dir} --local-spec-repo {tsp_dir} --commit {head_sha} --repo {repo_url}"

eng/tools/azure-sdk-tools/packaging_tools/package_utils.py

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,13 @@
1919
from . import build_packaging
2020
from .change_log import main as change_log_main
2121

22-
DEFAULT_DEST_FOLDER = "./dist"
23-
2422
_LOGGER = logging.getLogger(__name__)
2523

2624

2725
# prefolder: "sdk/compute"; name: "azure-mgmt-compute"
28-
def create_package(prefolder, name, dest_folder=DEFAULT_DEST_FOLDER):
26+
def create_package(prefolder, name):
2927
absdirpath = Path(prefolder, name).absolute()
30-
check_call(["python", "setup.py", "bdist_wheel", "-d", dest_folder], cwd=absdirpath)
31-
check_call(
32-
["python", "setup.py", "sdist", "--format", "zip", "-d", dest_folder],
33-
cwd=absdirpath,
34-
)
28+
check_call(["python", "-m", "build"], cwd=absdirpath)
3529

3630

3731
@return_origin_path
@@ -233,23 +227,47 @@ def check_file_with_packaging_tool(self):
233227

234228
# add `title` and update `is_stable` in pyproject.toml
235229
pyproject_toml = Path(self.whole_package_name) / "pyproject.toml"
230+
is_stable = self.tag_is_stable and self.next_version != "1.0.0b1"
236231
if pyproject_toml.exists():
237232
with open(pyproject_toml, "rb") as fd:
238233
toml_data = toml.load(fd)
239234
if "packaging" not in toml_data:
240235
toml_data["packaging"] = {}
241236
if title and not toml_data["packaging"].get("title"):
242237
toml_data["packaging"]["title"] = title
243-
toml_data["packaging"]["is_stable"] = self.tag_is_stable and self.next_version != "1.0.0b1"
238+
toml_data["packaging"]["is_stable"] = is_stable
244239
with open(pyproject_toml, "wb") as fd:
245240
tomlw.dump(toml_data, fd)
246241
_LOGGER.info(f"Update {pyproject_toml} successfully")
247242
else:
248243
_LOGGER.info(f"{os.getcwd()}/{pyproject_toml} does not exist")
249244

250-
build_packaging(output_folder=".", packages=[self.whole_package_name], build_conf=True)
245+
build_packaging(
246+
output_folder=".",
247+
packages=[self.whole_package_name],
248+
build_conf=True,
249+
template_names=["README.md", "__init__.py"],
250+
)
251251
_LOGGER.info("packaging_tools --build-conf successfully")
252252

253+
if pyproject_toml.exists():
254+
stable_classifier = "Development Status :: 5 - Production/Stable"
255+
beta_classifier = "Development Status :: 4 - Beta"
256+
257+
def edit_file(content: List[str]):
258+
for i in range(0, len(content)):
259+
if "Development Status" in content[i]:
260+
if is_stable and beta_classifier in content[i]:
261+
content[i] = content[i].replace(beta_classifier, stable_classifier)
262+
_LOGGER.info(f"Replace '{beta_classifier}' with '{stable_classifier}' in {pyproject_toml}")
263+
if (not is_stable) and stable_classifier in content[i]:
264+
content[i] = content[i].replace(stable_classifier, beta_classifier)
265+
_LOGGER.info(f"Replace '{stable_classifier}' with '{beta_classifier}' in {pyproject_toml}")
266+
break
267+
268+
modify_file(str(pyproject_toml), edit_file)
269+
_LOGGER.info(f"Check {pyproject_toml} for classifiers successfully")
270+
253271
def sdk_code_path(self) -> str:
254272
return str(Path(f"sdk/{self.sdk_folder}/{self.whole_package_name}"))
255273

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
1+
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore

scripts/auto_release/requirement.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ fastcore==1.3.25
88
tox==4.15.0
99
wheel==0.43.0
1010
setuptools==78.1.0
11-
build==1.0.3
11+
build==1.3.0
1212
tomli-w==1.0.0
1313
tomli==2.2.1

scripts/automation_init.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pip install tox==4.15.0 > /dev/null
77
pip install wheel==0.43.0 > /dev/null
88
pip install setuptools==78.1.0 > /dev/null
99
pip install setuptools-scm==8.3.0 > /dev/null
10+
pip install build==1.3.0 > /dev/null
1011

1112
# install tsp-client globally (local install may interfere with tooling)
1213
echo Install tsp-client

swagger_to_sdk_config_autorest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"include-x-ms-examples-original-file": true,
1010
"generate-sample": true,
1111
"generate-test": true,
12-
"keep-setup-py": true
12+
"package-mode": "azure-mgmt"
1313
},
1414
"advanced_options": {
1515
"create_sdk_pull_requests": true,

0 commit comments

Comments
 (0)