Skip to content

Commit 35c5935

Browse files
scbeddmccoyp
andauthored
Adding the ability to skip compatibility filtering (Azure#25813)
* adding the ability to skip the compatibility filter where appropriate Co-authored-by: McCoy Patiño <39780829+mccoyp@users.noreply.github.com>
1 parent fc9e6f9 commit 35c5935

File tree

10 files changed

+106
-70
lines changed

10 files changed

+106
-70
lines changed

scripts/devops_tasks/setup_execute_tests.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
create_code_coverage_params
2727
)
2828
from tox_harness import prep_and_run_tox
29-
from ci_tools.functions import discover_targeted_packages, filter_packages_by_compatibility_override
29+
from ci_tools.functions import discover_targeted_packages
3030

3131
logging.getLogger().setLevel(logging.INFO)
3232

@@ -280,9 +280,8 @@ def execute_global_install_and_test(
280280
dest="filter_type",
281281
default='Build',
282282
help="Filter type to identify eligible packages. for e.g. packages filtered in Build can pass filter type as Build,",
283-
choices=['Build', "Docs", "Regression", "Omit_management"]
283+
choices=['Build', "Docs", "Regression", "Omit_management", "None"]
284284
)
285-
286285
parser.add_argument(
287286
"-d",
288287
"--dest-dir",
@@ -301,21 +300,23 @@ def execute_global_install_and_test(
301300
else:
302301
target_dir = root_dir
303302

304-
targeted_packages = discover_targeted_packages(args.glob_string, target_dir, "", args.filter_type)
305-
compatible_targeted_packages = filter_packages_by_compatibility_override(targeted_packages)
303+
if args.filter_type == "None":
304+
args.filter_type = "Build"
305+
compatibility_filter = False
306+
else:
307+
compatibility_filter = True
306308

307-
if targeted_packages != compatible_targeted_packages:
308-
logging.info("At least one package incompatible with current platform was detected. Skipping: {}".format(set(targeted_packages) - set(compatible_targeted_packages)))
309+
targeted_packages = discover_targeted_packages(args.glob_string, target_dir, "", args.filter_type, compatibility_filter)
309310

310311
extended_pytest_args = []
311312

312-
if len(compatible_targeted_packages) == 0:
313+
if len(targeted_packages) == 0:
313314
exit(0)
314315

315316
if args.xdist:
316317
extended_pytest_args.extend(["-n", "8", "--dist=loadscope"])
317318

318319
if args.runtype != "none":
319-
execute_global_install_and_test(args, compatible_targeted_packages, extended_pytest_args)
320+
execute_global_install_and_test(args, targeted_packages, extended_pytest_args)
320321
else:
321-
prep_and_run_tox(compatible_targeted_packages, args, extended_pytest_args)
322+
prep_and_run_tox(targeted_packages, args, extended_pytest_args)

tools/azure-sdk-tools/ci_tools/functions.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"azure-mgmt-core",
4343
]
4444

45-
TEST_COMPATIBILITY_MAP = {"azure-core-tracing-opentelemetry": "<3.10"}
45+
TEST_COMPATIBILITY_MAP = {}
4646

4747
omit_regression = (
4848
lambda x: "nspkg" not in x
@@ -66,13 +66,25 @@
6666
}
6767

6868

69-
def filter_for_compatibility(package_set):
69+
def filter_for_compatibility(package_set: List[str]) -> List[str]:
70+
"""
71+
This function takes in a set of paths to python packages. It returns the set filtered by compatibility with the currently running python executable.
72+
If a package is unsupported by the executable, it will be omitted from the returned list.
73+
74+
A manual override list of these compatibilities is also supported, but requires code change to enable. Check TEST_COMPATIBILITY_MAP in this same file.
75+
76+
:param List[str] package_set: a list of paths to python packages. Each item can either be a package folder or a direct path to setup.py.
77+
"""
7078
collected_packages = []
7179
v = sys.version_info
7280
running_major_version = Version(".".join([str(v[0]), str(v[1]), str(v[2])]))
7381

7482
for pkg in package_set:
7583
spec_set = SpecifierSet(ParsedSetup.from_path(pkg).python_requires)
84+
pkg_specs_override = TEST_COMPATIBILITY_MAP.get(os.path.basename(pkg), None)
85+
86+
if pkg_specs_override:
87+
spec_set = SpecifierSet(pkg_specs_override)
7688

7789
if running_major_version in spec_set:
7890
collected_packages.append(pkg)
@@ -87,14 +99,6 @@ def compare_python_version(version_spec: str):
8799
return current_sys_version in spec_set
88100

89101

90-
def filter_packages_by_compatibility_override(package_set: List[str], resolve_basename: bool = True) -> List[str]:
91-
return [
92-
p
93-
for p in package_set
94-
if compare_python_version(TEST_COMPATIBILITY_MAP.get(os.path.basename(p) if resolve_basename else p, ">=2.7"))
95-
]
96-
97-
98102
def str_to_bool(input_string: str) -> bool:
99103
"""
100104
Takes a boolean string representation and returns a bool type value.
@@ -114,10 +118,17 @@ def discover_targeted_packages(
114118
target_root_dir: str,
115119
additional_contains_filter: str = "",
116120
filter_type: str = "Build",
121+
compatibility_filter: bool = True,
117122
) -> List[str]:
118123
"""
119124
During build and test, the set of targeted packages may expand or contract depending on the needs of the invocation.
120125
This function centralizes business and material requirements and outputs the set of packages that should be targeted.
126+
127+
:param str glob_string: The basic glob used to query packages within the repo. Defaults to "azure-*"
128+
:param str target_root_dir: The root directory in which globbing will begin.
129+
:param str additional_contains_filter: Additional filter option. Used when needing to provide one-off filtration that doesn't merit an additional filter_type. Defaults to empty string.
130+
:param str filter_type: One a string representing a filter function as a set of options. Options [ "Build", "Docs", "Regression", "Omit_management" ] Defaults to "Build".
131+
:param bool compatibility_filter: Enables or disables compatibility filtering of found packages. If the invoking python executable does not match a found package's specifiers, the package will be omitted. Defaults to True.
121132
"""
122133
if glob_string:
123134
individual_globs = glob_string.split(",")
@@ -137,12 +148,14 @@ def discover_targeted_packages(
137148
# if we have individually queued this specific package, it's obvious that we want to build it specifically
138149
# in this case, do not honor the omission list
139150
if len(collected_directories) == 1:
140-
pkg_set_ci_filtered = filter_for_compatibility(collected_directories)
151+
if compatibility_filter:
152+
pkg_set_ci_filtered = filter_for_compatibility(collected_directories)
141153
# however, if there are multiple packages being built, we should honor the omission list and NOT build the omitted
142154
# packages
143155
else:
144156
allowed_package_set = remove_omitted_packages(collected_directories)
145-
pkg_set_ci_filtered = filter_for_compatibility(allowed_package_set)
157+
if compatibility_filter:
158+
pkg_set_ci_filtered = filter_for_compatibility(allowed_package_set)
146159

147160
# Apply filter based on filter type. for e.g. Docs, Regression, Management
148161
pkg_set_ci_filtered = list(filter(omit_function_dict.get(filter_type, omit_build), pkg_set_ci_filtered))
@@ -265,7 +278,7 @@ def process_requires(setup_py_path: str):
265278
# \d+ <followed by number of digits N>
266279
# )?
267280
# )?
268-
rx = r'{}(((a|b|rc)\d+)?(\.post\d+)?)?'.format(base_version)
281+
rx = r"{}(((a|b|rc)\d+)?(\.post\d+)?)?".format(base_version)
269282
new_req = re.sub(rx, "{}{}1".format(base_version, DEV_BUILD_IDENTIFIER), str(req), flags=re.IGNORECASE)
270283
logging.info("New requirement for package {0}: {1}".format(pkg_name, new_req))
271284
requirement_to_update[old_req] = new_req

tools/azure-sdk-tools/devtools_testutils/proxy_fixtures.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ def sanitize_batch(self, variables: "Dict[str, str]") -> "Dict[str, str]":
6363
current_values = {variable: self.sanitize(variable, variables[variable]) for variable in variables}
6464
return current_values
6565

66-
6766
def get(self, variable: str) -> str:
6867
"""Returns the value of the specified environment variable in live mode, or the sanitized value in playback.
6968

tools/azure-sdk-tools/devtools_testutils/sanitizers.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -571,11 +571,7 @@ def _send_recording_options_request(parameters: dict, headers: "Optional[dict]"
571571
if is_live_and_not_recording():
572572
return
573573

574-
response = requests.post(
575-
f"{PROXY_URL}/Admin/SetRecordingOptions",
576-
headers=headers,
577-
json=parameters
578-
)
574+
response = requests.post(f"{PROXY_URL}/Admin/SetRecordingOptions", headers=headers, json=parameters)
579575
response.raise_for_status()
580576

581577

tools/azure-sdk-tools/packaging_tools/auto_codegen.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@
88
CONFIG_FILE,
99
)
1010
from .generate_sdk import generate
11-
from .generate_utils import (get_package_names, init_new_service, update_servicemetadata, judge_tag_preview,
12-
format_samples, gen_dpg, dpg_relative_folder)
11+
from .generate_utils import (
12+
get_package_names,
13+
init_new_service,
14+
update_servicemetadata,
15+
judge_tag_preview,
16+
format_samples,
17+
gen_dpg,
18+
dpg_relative_folder,
19+
)
1320

1421
_LOGGER = logging.getLogger(__name__)
1522

23+
1624
def main(generate_input, generate_output):
1725
with open(generate_input, "r") as reader:
1826
data = json.load(reader)
@@ -25,11 +33,18 @@ def main(generate_input, generate_output):
2533
for input_readme in data["relatedReadmeMdFiles"]:
2634
relative_path_readme = str(Path(spec_folder, input_readme))
2735
_LOGGER.info(f"[CODEGEN]({input_readme})codegen begin")
28-
if 'resource-manager' in input_readme:
29-
config = generate(CONFIG_FILE, sdk_folder, [], relative_path_readme, spec_folder, force_generation=True,
30-
python_tag=python_tag)
36+
if "resource-manager" in input_readme:
37+
config = generate(
38+
CONFIG_FILE,
39+
sdk_folder,
40+
[],
41+
relative_path_readme,
42+
spec_folder,
43+
force_generation=True,
44+
python_tag=python_tag,
45+
)
3146
else:
32-
config = gen_dpg(input_readme, data.get('autorestConfig', ''), dpg_relative_folder(spec_folder))
47+
config = gen_dpg(input_readme, data.get("autorestConfig", ""), dpg_relative_folder(spec_folder))
3348
package_names = get_package_names(sdk_folder)
3449
_LOGGER.info(f"[CODEGEN]({input_readme})codegen end. [(packages:{str(package_names)})]")
3550

tools/azure-sdk-tools/packaging_tools/change_log.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ def build_md(self):
3333
if self.features:
3434
_build_md(sorted(set(self.features), key=self.features.index), "### Features Added", buffer)
3535
if self.breaking_changes:
36-
_build_md(sorted(set(self.breaking_changes), key=self.breaking_changes.index), "### Breaking Changes", buffer)
36+
_build_md(
37+
sorted(set(self.breaking_changes), key=self.breaking_changes.index), "### Breaking Changes", buffer
38+
)
3739
if not (self.features or self.breaking_changes) and self.optional_features:
38-
_build_md(sorted(set(self.optional_features), key=self.optional_features.index), "### Features Added", buffer)
40+
_build_md(
41+
sorted(set(self.optional_features), key=self.optional_features.index), "### Features Added", buffer
42+
)
3943

4044
return "\n".join(buffer).strip()
4145

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,11 @@ def gen_general_namespace(package_name: str) -> str:
188188
def gen_dpg_config_single_client(origin_config: Dict[str, Any], spec_folder: str) -> str:
189189
package_name = Path(origin_config["output-folder"]).parts[-1]
190190
readme_config = gen_basic_config(origin_config, spec_folder)
191-
readme_config.update({
192-
"namespace": gen_general_namespace(package_name),
193-
})
191+
readme_config.update(
192+
{
193+
"namespace": gen_general_namespace(package_name),
194+
}
195+
)
194196
readme_content = yaml_block(yaml.safe_dump(readme_config), "### Settings")
195197
return add_config_title(readme_content)
196198

tools/azure-sdk-tools/packaging_tools/sdk_generator.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@
77

88
from .swaggertosdk.SwaggerToSdkCore import CONFIG_FILE
99
from .generate_sdk import generate
10-
from .generate_utils import (get_package_names, init_new_service, update_servicemetadata, judge_tag_preview,
11-
format_samples, gen_dpg)
10+
from .generate_utils import (
11+
get_package_names,
12+
init_new_service,
13+
update_servicemetadata,
14+
judge_tag_preview,
15+
format_samples,
16+
gen_dpg,
17+
)
1218

1319
_LOGGER = logging.getLogger(__name__)
1420

@@ -18,21 +24,22 @@ def main(generate_input, generate_output):
1824
data = json.load(reader)
1925
_LOGGER.info(f"auto_package input: {data}")
2026

21-
spec_folder = re.sub('specification', '', data["specFolder"])
27+
spec_folder = re.sub("specification", "", data["specFolder"])
2228
sdk_folder = "."
2329
result = {}
24-
python_tag = data.get('python_tag')
30+
python_tag = data.get("python_tag")
2531
package_total = set()
2632

2733
input_readme = data["relatedReadmeMdFile"]
2834
relative_path_readme = str(Path(spec_folder, input_readme))
2935
_LOGGER.info(f"[CODEGEN]({input_readme})codegen begin")
3036

31-
if 'resource-manager' in input_readme:
32-
config = generate(CONFIG_FILE, sdk_folder, [], relative_path_readme, spec_folder, force_generation=True,
33-
python_tag=python_tag)
37+
if "resource-manager" in input_readme:
38+
config = generate(
39+
CONFIG_FILE, sdk_folder, [], relative_path_readme, spec_folder, force_generation=True, python_tag=python_tag
40+
)
3441
else:
35-
config = gen_dpg(input_readme, data.get('autorestConfig', ''), spec_folder)
42+
config = gen_dpg(input_readme, data.get("autorestConfig", ""), spec_folder)
3643
package_names = get_package_names(sdk_folder)
3744
_LOGGER.info(f"[CODEGEN]({input_readme})codegen end. [(packages:{str(package_names)})]")
3845

tools/azure-sdk-tools/pypi_tools/pypi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def get_pypi_xmlrpc_client():
1212
class PyPIClient:
1313
def __init__(self, host="https://pypi.org"):
1414
import requests
15+
1516
self._host = host
1617
self._session = requests.Session()
1718

tools/azure-sdk-tools/tests/test_parse_functionality.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import pdb
55
from unittest.mock import patch
66

7-
package_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
7+
package_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
8+
89

910
def test_parse_require():
1011
test_scenarios = [
@@ -14,15 +15,15 @@ def test_parse_require():
1415
"msrest==0.6.10",
1516
"msrest<0.6.10",
1617
"msrest>0.6.9",
17-
"azure-core<2.0.0,>=1.2.2"
18+
"azure-core<2.0.0,>=1.2.2",
1819
]
1920

2021
for scenario in test_scenarios:
2122
result = parse_require(scenario)
2223

23-
assert(result[0] is not None)
24-
assert(result[1] is not None)
25-
assert(isinstance(result[1], SpecifierSet))
24+
assert result[0] is not None
25+
assert result[1] is not None
26+
assert isinstance(result[1], SpecifierSet)
2627

2728

2829
def test_parse_require_with_no_spec():
@@ -31,10 +32,11 @@ def test_parse_require_with_no_spec():
3132
for scenario in spec_scenarios:
3233
result = parse_require(scenario)
3334

34-
assert(result[0] == scenario.replace("_", "-"))
35-
assert(result[1] is None)
35+
assert result[0] == scenario.replace("_", "-")
36+
assert result[1] is None
3637

37-
@patch('ci_tools.parsing.parse_functions.read_setup_py_content')
38+
39+
@patch("ci_tools.parsing.parse_functions.read_setup_py_content")
3840
def test_sdk_sample_setup(test_patch):
3941
test_patch.return_value = """
4042
import re
@@ -94,19 +96,15 @@ def test_sdk_sample_setup(test_patch):
9496
],
9597
)
9698
"""
97-
99+
98100
result = ParsedSetup.from_path(package_root)
99101

100-
assert(result.name == "azure-core")
101-
assert(result.version == "1.21.0")
102-
assert(result.python_requires == ">=3.7")
103-
assert(result.requires == ['requests>=2.18.4', 'six>=1.11.0', 'typing-extensions>=4.0.1'])
104-
assert(result.is_new_sdk == True)
105-
assert(result.setup_filename == os.path.join(package_root, "setup.py"))
106-
assert(result.namespace == "ci_tools")
107-
assert("pytyped" in result.package_data)
108-
assert(result.include_package_data == True)
109-
110-
111-
112-
102+
assert result.name == "azure-core"
103+
assert result.version == "1.21.0"
104+
assert result.python_requires == ">=3.7"
105+
assert result.requires == ["requests>=2.18.4", "six>=1.11.0", "typing-extensions>=4.0.1"]
106+
assert result.is_new_sdk == True
107+
assert result.setup_filename == os.path.join(package_root, "setup.py")
108+
assert result.namespace == "ci_tools"
109+
assert "pytyped" in result.package_data
110+
assert result.include_package_data == True

0 commit comments

Comments
 (0)