Skip to content

Commit b349e17

Browse files
thinkallCopilot
andcommitted
test: consolidate duplicated Spark session setup into shared helper
Three test modules each rebuilt the same SynapseML/MLflow-Spark Spark session from scratch with identical configuration: test/spark/test_0sparkml.py test/spark/test_internal_mlflow.py (in _init_spark_for_main) test/automl/test_extra_models.py Move the SparkSession.builder configuration, log_model_allowlist override, and disable/restore_spark_ansi_mode + atexit cleanup into a single test-only helper at test/spark/_init_spark.py exposing: init_spark_session(app_name, master) - build/fetch the session setup_spark_for_tests(app_name, master) - returns (spark, skip_spark) with platform/import gating and ANSI mode handling Each test module now calls the helper instead of duplicating the Maven-coordinates / config block. No behavioural change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 383fd94 commit b349e17

4 files changed

Lines changed: 111 additions & 107 deletions

File tree

test/automl/test_extra_models.py

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
1-
import atexit
21
import os
32
import sys
43
import unittest
5-
import warnings
64
from collections import defaultdict
75

8-
import mlflow
96
import numpy as np
107
import pandas as pd
118
import pytest
129
import scipy
13-
from packaging.version import Version
1410
from sklearn.datasets import load_breast_cancer, load_diabetes, load_iris
1511
from sklearn.model_selection import train_test_split
1612

1713
from flaml import AutoML
1814
from flaml.automl.ml import sklearn_metric_loss_score
19-
from flaml.automl.spark import disable_spark_ansi_mode, restore_spark_ansi_mode
20-
from flaml.tune.spark.utils import check_spark
2115

2216
try:
2317
import pytorch_lightning
@@ -30,51 +24,22 @@
3024

3125
leaderboard = defaultdict(dict)
3226

33-
warnings.simplefilter(action="ignore")
3427
if sys.platform == "darwin" or "nt" in os.name:
3528
# skip this test if the platform is not linux
3629
skip_spark = True
3730
else:
3831
try:
39-
import pyspark
32+
from test.spark._init_spark import setup_spark_for_tests
33+
4034
from pyspark.ml.evaluation import MulticlassClassificationEvaluator, RegressionEvaluator
4135
from pyspark.ml.feature import VectorAssembler
4236

4337
from flaml.automl.spark.utils import to_pandas_on_spark
4438

45-
spark = (
46-
pyspark.sql.SparkSession.builder.appName("MyApp")
47-
.master("local[2]")
48-
.config(
49-
"spark.jars.packages",
50-
(
51-
"com.microsoft.azure:synapseml_2.12:1.0.14,"
52-
"org.apache.hadoop:hadoop-azure:3.3.5,"
53-
"com.microsoft.azure:azure-storage:8.6.6,"
54-
f"org.mlflow:mlflow-spark_2.12:{mlflow.__version__}"
55-
if Version(mlflow.__version__) >= Version("2.9.0")
56-
else f"org.mlflow:mlflow-spark:{mlflow.__version__}"
57-
),
58-
)
59-
.config("spark.jars.repositories", "https://mmlspark.azureedge.net/maven")
60-
.config("spark.sql.debug.maxToStringFields", "100")
61-
.config("spark.driver.extraJavaOptions", "-Xss1m")
62-
.config("spark.executor.extraJavaOptions", "-Xss1m")
63-
.getOrCreate()
64-
)
65-
spark.sparkContext._conf.set(
66-
"spark.mlflow.pysparkml.autolog.logModelAllowlistFile",
67-
"https://mmlspark.blob.core.windows.net/publicwasb/log_model_allowlist.txt",
68-
)
69-
# spark.sparkContext.setLogLevel("ERROR")
70-
spark_available, _ = check_spark()
71-
skip_spark = not spark_available
39+
spark, skip_spark = setup_spark_for_tests("MyApp")
7240
except ImportError:
7341
skip_spark = True
7442

75-
spark, ansi_conf, adjusted = disable_spark_ansi_mode()
76-
atexit.register(restore_spark_ansi_mode, spark, ansi_conf, adjusted)
77-
7843

7944
def _test_regular_models(estimator_list, task):
8045
if isinstance(estimator_list, str):

test/spark/_init_spark.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""Single source of truth for setting up the Spark session shared by FLAML's
2+
Spark-dependent test modules.
3+
4+
Several test files (``test/spark/test_0sparkml.py``,
5+
``test/spark/test_internal_mlflow.py``, ``test/automl/test_extra_models.py``)
6+
historically duplicated the same large ``SparkSession.builder`` configuration
7+
(synapseml + hadoop-azure + mlflow-spark JARs, MMLSpark Maven repo,
8+
log_model_allowlistFile, ANSI-mode handling). Keeping the duplicated copies
9+
in sync turned out to be brittle — this helper centralises it.
10+
11+
The module name starts with an underscore so pytest will not try to collect
12+
it as a test module.
13+
"""
14+
15+
from __future__ import annotations
16+
17+
import atexit
18+
import os
19+
import sys
20+
import warnings
21+
22+
import mlflow
23+
from packaging.version import Version
24+
25+
from flaml.automl.spark import disable_spark_ansi_mode, restore_spark_ansi_mode
26+
from flaml.tune.spark.utils import check_spark
27+
28+
29+
def _spark_jars_packages() -> str:
30+
"""Maven coordinates for the JARs added to the Spark session."""
31+
return (
32+
"com.microsoft.azure:synapseml_2.12:1.0.14,"
33+
"org.apache.hadoop:hadoop-azure:3.3.5,"
34+
"com.microsoft.azure:azure-storage:8.6.6,"
35+
f"org.mlflow:mlflow-spark_2.12:{mlflow.__version__}"
36+
if Version(mlflow.__version__) >= Version("2.9.0")
37+
else f"org.mlflow:mlflow-spark:{mlflow.__version__}"
38+
)
39+
40+
41+
def init_spark_session(app_name: str = "MyApp", master: str = "local[2]"):
42+
"""Build (or fetch) the SparkSession used by FLAML's Spark tests.
43+
44+
Imports ``pyspark`` lazily so this module remains importable in
45+
environments where pyspark is not installed (collection-time safety).
46+
"""
47+
import pyspark
48+
49+
spark = (
50+
pyspark.sql.SparkSession.builder.appName(app_name)
51+
.master(master)
52+
.config("spark.jars.packages", _spark_jars_packages())
53+
.config("spark.jars.repositories", "https://mmlspark.azureedge.net/maven")
54+
.config("spark.sql.debug.maxToStringFields", "100")
55+
.config("spark.driver.extraJavaOptions", "-Xss1m")
56+
.config("spark.executor.extraJavaOptions", "-Xss1m")
57+
.getOrCreate()
58+
)
59+
spark.sparkContext._conf.set(
60+
"spark.mlflow.pysparkml.autolog.logModelAllowlistFile",
61+
"https://mmlspark.blob.core.windows.net/publicwasb/log_model_allowlist.txt",
62+
)
63+
return spark
64+
65+
66+
def setup_spark_for_tests(
67+
app_name: str = "MyApp",
68+
master: str = "local[2]",
69+
) -> tuple[object | None, bool]:
70+
"""Initialise Spark for the importing test module.
71+
72+
Returns ``(spark, skip_spark)``:
73+
74+
* ``spark`` -- the configured ``SparkSession`` (or ``None`` when
75+
pyspark is not available, e.g. on macOS / Windows
76+
runners or when the package is not installed).
77+
* ``skip_spark`` -- ``True`` when the Spark-dependent tests in the caller
78+
should be skipped. Suitable for use with
79+
``pytest.mark.skipif(skip_spark, ...)``.
80+
81+
ANSI-mode handling matches the prior duplicated setup: it is invoked
82+
unconditionally and ``restore_spark_ansi_mode`` is registered with
83+
``atexit`` (this is a no-op when no active Spark session exists).
84+
"""
85+
warnings.simplefilter(action="ignore")
86+
87+
spark: object | None = None
88+
skip_spark = False
89+
90+
if sys.platform == "darwin" or "nt" in os.name:
91+
skip_spark = True
92+
else:
93+
try:
94+
spark = init_spark_session(app_name=app_name, master=master)
95+
spark_available, _ = check_spark()
96+
skip_spark = not spark_available
97+
except ImportError:
98+
skip_spark = True
99+
100+
active_spark, ansi_conf, adjusted = disable_spark_ansi_mode()
101+
atexit.register(restore_spark_ansi_mode, active_spark, ansi_conf, adjusted)
102+
103+
return spark, skip_spark

test/spark/test_0sparkml.py

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,28 @@
1-
import atexit
21
import os
32
import sys
4-
import warnings
53

6-
import mlflow
74
import numpy as np
85
import pytest
96
import sklearn.datasets as skds
10-
from packaging.version import Version
117

128
from flaml import AutoML
139
from flaml.automl.data import auto_convert_dtypes_pandas, auto_convert_dtypes_spark, get_random_dataframe
14-
from flaml.automl.spark import disable_spark_ansi_mode, restore_spark_ansi_mode
15-
from flaml.tune.spark.utils import check_spark
1610

17-
warnings.simplefilter(action="ignore")
1811
if sys.platform == "darwin" or "nt" in os.name:
1912
# skip this test if the platform is not linux
2013
skip_spark = True
2114
else:
2215
try:
23-
import pyspark
16+
from test.spark._init_spark import setup_spark_for_tests
17+
2418
from pyspark.ml.feature import VectorAssembler
2519

2620
from flaml.automl.spark.utils import to_pandas_on_spark
2721

28-
spark = (
29-
pyspark.sql.SparkSession.builder.appName("MyApp")
30-
.master("local[2]")
31-
.config(
32-
"spark.jars.packages",
33-
(
34-
"com.microsoft.azure:synapseml_2.12:1.0.14,"
35-
"org.apache.hadoop:hadoop-azure:3.3.5,"
36-
"com.microsoft.azure:azure-storage:8.6.6,"
37-
f"org.mlflow:mlflow-spark_2.12:{mlflow.__version__}"
38-
if Version(mlflow.__version__) >= Version("2.9.0")
39-
else f"org.mlflow:mlflow-spark:{mlflow.__version__}"
40-
),
41-
)
42-
.config("spark.jars.repositories", "https://mmlspark.azureedge.net/maven")
43-
.config("spark.sql.debug.maxToStringFields", "100")
44-
.config("spark.driver.extraJavaOptions", "-Xss1m")
45-
.config("spark.executor.extraJavaOptions", "-Xss1m")
46-
# .config("spark.executor.memory", "48G")
47-
# .config("spark.driver.memory", "48G")
48-
.getOrCreate()
49-
)
50-
spark.sparkContext._conf.set(
51-
"spark.mlflow.pysparkml.autolog.logModelAllowlistFile",
52-
"https://mmlspark.blob.core.windows.net/publicwasb/log_model_allowlist.txt",
53-
)
54-
# spark.sparkContext.setLogLevel("ERROR")
55-
spark_available, _ = check_spark()
56-
skip_spark = not spark_available
22+
spark, skip_spark = setup_spark_for_tests("MyApp")
5723
except ImportError:
5824
skip_spark = True
5925

60-
spark, ansi_conf, adjusted = disable_spark_ansi_mode()
61-
atexit.register(restore_spark_ansi_mode, spark, ansi_conf, adjusted)
62-
6326
if sys.version_info >= (3, 11):
6427
skip_py311 = True
6528
else:

test/spark/test_internal_mlflow.py

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import mlflow
99
import pyspark
1010
import pytest
11-
from packaging.version import Version
1211
from pyspark.ml.evaluation import RegressionEvaluator
1312
from pyspark.ml.feature import VectorAssembler
1413
from sklearn.datasets import fetch_california_housing, load_diabetes
@@ -287,35 +286,9 @@ def test_exit_pyspark_autolog():
287286

288287

289288
def _init_spark_for_main():
290-
import pyspark
289+
from test.spark._init_spark import setup_spark_for_tests
291290

292-
spark = (
293-
pyspark.sql.SparkSession.builder.appName("MyApp")
294-
.master("local[2]")
295-
.config(
296-
"spark.jars.packages",
297-
(
298-
"com.microsoft.azure:synapseml_2.12:1.0.14,"
299-
"org.apache.hadoop:hadoop-azure:3.3.5,"
300-
"com.microsoft.azure:azure-storage:8.6.6,"
301-
f"org.mlflow:mlflow-spark_2.12:{mlflow.__version__}"
302-
if Version(mlflow.__version__) >= Version("2.9.0")
303-
else f"org.mlflow:mlflow-spark:{mlflow.__version__}"
304-
),
305-
)
306-
.config("spark.jars.repositories", "https://mmlspark.azureedge.net/maven")
307-
.config("spark.sql.debug.maxToStringFields", "100")
308-
.config("spark.driver.extraJavaOptions", "-Xss1m")
309-
.config("spark.executor.extraJavaOptions", "-Xss1m")
310-
.getOrCreate()
311-
)
312-
spark.sparkContext._conf.set(
313-
"spark.mlflow.pysparkml.autolog.logModelAllowlistFile",
314-
"https://mmlspark.blob.core.windows.net/publicwasb/log_model_allowlist.txt",
315-
)
316-
317-
spark, ansi_conf, adjusted = disable_spark_ansi_mode()
318-
atexit.register(restore_spark_ansi_mode, spark, ansi_conf, adjusted)
291+
setup_spark_for_tests("MyApp")
319292

320293

321294
if __name__ == "__main__":

0 commit comments

Comments
 (0)