|
6 | 6 |
|
7 | 7 | # pyre-strict |
8 | 8 | import logging |
| 9 | +import os |
9 | 10 | import random |
10 | 11 | import string |
11 | 12 | from unittest.mock import patch |
12 | 13 |
|
| 14 | +import sqlalchemy |
13 | 15 | from ax.core.base_trial import BaseTrial |
14 | 16 | from ax.core.experiment import Experiment |
15 | 17 | from ax.core.trial import Trial |
16 | 18 | from ax.core.trial_status import TrialStatus |
17 | 19 | from ax.generation_strategy.generation_strategy import GenerationStrategy |
| 20 | +from ax.storage.sqa_store import with_db_settings_base as _wdb_module |
18 | 21 | from ax.storage.sqa_store.db import init_test_engine_and_session_factory |
19 | 22 | from ax.storage.sqa_store.load import ( |
20 | 23 | _load_experiment, |
@@ -396,3 +399,47 @@ def test_try_load_generation_strategy(self) -> None: |
396 | 399 | lg.output[0], |
397 | 400 | ) |
398 | 401 | self.assertEqual(output, generation_strategy) |
| 402 | + |
| 403 | + |
| 404 | +class TestSQLAlchemyDualVersionCompat(TestCase): |
| 405 | + """Self-proving checks that the dual-version SA 2.0 BUCK targets actually |
| 406 | + resolved their constraint_overrides and that the SA 2.0 hard guard is gone. |
| 407 | +
|
| 408 | + Part of the SA 2.0 dual-version migration (T163607006). |
| 409 | + """ |
| 410 | + |
| 411 | + def test_module_level_dbsettings_is_defined(self) -> None: |
| 412 | + """The SA 2.0 hard guard previously set DBSettings = None at module level |
| 413 | + when SA major > 1, breaking WithDBSettingsBase.__init__ type checks. Now |
| 414 | + that the guard is removed, DBSettings must always resolve to the real |
| 415 | + type when SQLAlchemy is importable. Uses getattr because DBSettings is |
| 416 | + conditionally defined in a try/except in with_db_settings_base. |
| 417 | + """ |
| 418 | + # pyre-ignore[16]: DBSettings is conditionally defined in with_db_settings_base. |
| 419 | + module_dbsettings = getattr(_wdb_module, "DBSettings", None) |
| 420 | + self.assertIsNotNone( |
| 421 | + module_dbsettings, |
| 422 | + "with_db_settings_base.DBSettings is None -- guard removal regressed", |
| 423 | + ) |
| 424 | + self.assertIs(module_dbsettings, DBSettings) |
| 425 | + |
| 426 | + def test_sa_major_matches_buck_target(self) -> None: |
| 427 | + """When the BUCK target sets EXPECTED_SA_MAJOR, assert the runtime |
| 428 | + SQLAlchemy major matches. Makes :tests vs :tests_sa2 self-proving. |
| 429 | + Skipped when EXPECTED_SA_MAJOR is unset (e.g., local one-off invocations). |
| 430 | + """ |
| 431 | + expected_major_str = os.environ.get("EXPECTED_SA_MAJOR") |
| 432 | + if expected_major_str is None: |
| 433 | + self.skipTest( |
| 434 | + "EXPECTED_SA_MAJOR not set; only enforced under the dual-version " |
| 435 | + "BUCK targets that pin SQLAlchemy via constraint_overrides" |
| 436 | + ) |
| 437 | + # pyre-ignore[16]: Module `sqlalchemy` has no attribute `__version__`. |
| 438 | + actual_version = sqlalchemy.__version__ |
| 439 | + actual_major = int(actual_version.split(".")[0]) |
| 440 | + self.assertEqual( |
| 441 | + actual_major, |
| 442 | + int(expected_major_str), |
| 443 | + f"BUCK target expected SQLAlchemy major {expected_major_str}, " |
| 444 | + f"got {actual_version}", |
| 445 | + ) |
0 commit comments