Skip to content

Commit f645daf

Browse files
committed
fix: circular imports
1 parent f291758 commit f645daf

File tree

18 files changed

+157
-113
lines changed

18 files changed

+157
-113
lines changed

.gitmodules

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
[submodule "tests_integration/definitions/conda_forge_pinning/resources/feedstock"]
2-
path = tests_integration/definitions/conda_forge_pinning/resources/feedstock
2+
path = tests_integration/lib/_definitions/conda_forge_pinning/resources/feedstock
33
url = https://github.com/conda-forge/conda-forge-pinning-feedstock.git
44
[submodule "tests_integration/definitions/pydantic/resources/feedstock"]
5-
path = tests_integration/definitions/pydantic/resources/feedstock
5+
path = tests_integration/lib/_definitions/pydantic/resources/feedstock
66
url = https://github.com/conda-forge/pydantic-feedstock.git
77
[submodule "tests_integration/definitions/pydantic/resources/feedstock_v1"]
8-
path = tests_integration/definitions/pydantic/resources/feedstock_v1
8+
path = tests_integration/lib/_definitions/pydantic/resources/feedstock_v1
99
url = https://github.com/conda-forge/pydantic-feedstock.git

tests_integration/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ account) contains a special version of the [cf-graph-countyfair](https://github.
1818
the bot uses during testing.
1919

2020
## Test Cases Definition
21-
The integration tests are defined in the [definitions](definitions) directory. The following directory structure is
21+
The integration tests are defined in the [lib/_definitions](lib/_definitions) directory. The following directory structure is
2222
used (using `pydantic` and `llvmdev` as example feedstocks):
2323

2424
```text
@@ -50,18 +50,18 @@ Also, a test case is always bound to one specific feedstock.
5050
To define a test case, create a subclass of `tests_integration.lib.TestCase` in the `__init__.py` file of
5151
your feedstock. You can name it arbitrarily.
5252
Referring to the minimal `VersionUpdate` test case in the
53-
[pydantic module](definitions/pydantic/__init__.py),
53+
[pydantic module](lib/_definitions/pydantic/__init__.py),
5454
your class has to implement three methods:
5555

5656
1. `get_router()` should return an `APIRouter` object to define mock responses for specific HTTP requests. All web requests are intercepted by an HTTP proxy.
5757
Refer to `tests_integration.lib.get_transparent_urls` to define URLs that should not be intercepted.
5858

59-
2. `prepare(helper: IntegrationTestHelper)` for setting up your test case. Usually, you will want to
60-
overwrite the feedstock repository in the test environment. The `IntegrationTestHelper` provides methods to interact
59+
2. `prepare(helper: AbstractIntegrationTestHelper)` for setting up your test case. Usually, you will want to
60+
overwrite the feedstock repository in the test environment. The `AbstractIntegrationTestHelper` provides methods to interact
6161
with the test environment.
6262

63-
3. A function `validate(helper: IntegrationTestHelper)` for validating the state after the bot has run.
64-
The `IntegrationTestHelper` provides convenience methods such as `assert_version_pr_present` to check for the presence
63+
3. A function `validate(helper: AbstractIntegrationTestHelper)` for validating the state after the bot has run.
64+
The `AbstractIntegrationTestHelper` provides convenience methods such as `assert_version_pr_present` to check for the presence
6565
of a version update PR.
6666

6767
The creation of GitHub repositories in the test environment is done automatically based on the directory structure.

tests_integration/definitions/__init__.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests_integration/lib/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ._collect_test_scenarios import get_all_test_scenario_ids, get_test_scenario
2+
from ._definitions.base_classes import AbstractIntegrationTestHelper, TestCase
23
from ._integration_test_helper import IntegrationTestHelper
34
from ._run_test_cases import (
45
close_all_open_pull_requests,
@@ -15,7 +16,6 @@
1516
get_transparent_urls,
1617
setup_logging,
1718
)
18-
from ._test_case import TestCase
1919

2020
__all__ = [
2121
"get_all_test_scenario_ids",
@@ -32,5 +32,6 @@
3232
"ENV_TEST_SCENARIO_ID",
3333
"VIRTUAL_PROXY_HOSTNAME",
3434
"VIRTUAL_PROXY_PORT",
35+
"AbstractIntegrationTestHelper",
3536
"TestCase",
3637
]

tests_integration/lib/_collect_test_scenarios.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import os
22
import random
33

4-
from tests_integration.definitions import TEST_CASE_MAPPING
5-
4+
from ._definitions import TEST_CASE_MAPPING, TestCase
65
from ._shared import ENV_GITHUB_RUN_ID
7-
from ._test_case import TestCase
86

97

108
def get_number_of_test_scenarios() -> int:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from . import conda_forge_pinning, pydantic
2+
from .base_classes import AbstractIntegrationTestHelper, GitHubAccount, TestCase
3+
4+
TEST_CASE_MAPPING: dict[str, list[TestCase]] = {
5+
"conda-forge-pinning": conda_forge_pinning.ALL_TEST_CASES,
6+
"pydantic": pydantic.ALL_TEST_CASES,
7+
}
8+
"""
9+
Maps from feedstock name to a list of all test cases for that feedstock.
10+
"""
11+
12+
__all__ = [
13+
"AbstractIntegrationTestHelper",
14+
"GitHubAccount",
15+
"TestCase",
16+
"TEST_CASE_MAPPING",
17+
]
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""
2+
This file contains classes that both _definitions and lib are referring to.
3+
To avoid circular imports, it needs to be separate.
4+
"""
5+
6+
from abc import ABC
7+
from enum import StrEnum
8+
from pathlib import Path
9+
10+
from fastapi import APIRouter
11+
12+
13+
class GitHubAccount(StrEnum):
14+
CONDA_FORGE_ORG = "conda-forge-bot-staging"
15+
BOT_USER = "regro-cf-autotick-bot-staging"
16+
REGRO_ORG = "regro-staging"
17+
18+
19+
class AbstractIntegrationTestHelper(ABC):
20+
"""
21+
This is an abstract base class for the IntegrationTestHelper in tests_integration.lib.
22+
Without this class, we cannot refer to IntegrationTestHelper in the definitions module
23+
because it would create a circular import. So we refer to this class instead
24+
and make sure that IntegrationTestHelper inherits from this class.
25+
"""
26+
27+
def overwrite_feedstock_contents(
28+
self, feedstock_name: str, source_dir: Path, branch: str = "main"
29+
):
30+
"""
31+
Overwrite the contents of the feedstock with the contents of the source directory.
32+
This prunes the entire git history.
33+
34+
:param feedstock_name: The name of the feedstock repository, without the "-feedstock" suffix.
35+
:param source_dir: The directory containing the new contents of the feedstock.
36+
:param branch: The branch to overwrite.
37+
"""
38+
pass
39+
40+
def overwrite_github_repository(
41+
self,
42+
owner_account: GitHubAccount,
43+
repo_name: str,
44+
source_dir: Path,
45+
branch: str = "main",
46+
):
47+
"""
48+
Overwrite the contents of the repository with the contents of the source directory.
49+
This prunes the entire git history.
50+
51+
:param owner_account: The owner of the repository.
52+
:param repo_name: The name of the repository.
53+
:param source_dir: The directory containing the new contents of the repository.
54+
:param branch: The branch to overwrite.
55+
"""
56+
pass
57+
58+
def assert_version_pr_present(
59+
self,
60+
feedstock: str,
61+
new_version: str,
62+
new_hash: str,
63+
old_version: str,
64+
old_hash: str,
65+
):
66+
"""
67+
Asserts that the bot has opened a version update PR.
68+
69+
:param feedstock: The feedstock we expect the PR for, without the -feedstock suffix.
70+
:param new_version: The new version that is expected.
71+
:param new_hash: The new SHA-256 source artifact hash.
72+
:param old_version: The old version of the feedstock, to check that it no longer appears in the recipe.
73+
:param old_hash: The old SHA-256 source artifact hash, to check that it no longer appears in the recipe.
74+
75+
:raises AssertionError: if the assertion fails
76+
"""
77+
pass
78+
79+
80+
class TestCase(ABC):
81+
"""
82+
Abstract base class for a single test case in a scenario.
83+
Per test case, there is exactly one instance of this class statically created
84+
in the definition of the ALL_TEST_CASES list of the feedstock module.
85+
Note that a test case (i.e. an instance of this class) might be run multiple times,
86+
so be careful with state you keep in the instance.
87+
"""
88+
89+
def get_router(self) -> APIRouter:
90+
"""
91+
Return the FastAPI router for the test case.
92+
"""
93+
pass
94+
95+
def prepare(self, helper: AbstractIntegrationTestHelper):
96+
"""
97+
Prepare the test case using the given helper.
98+
"""
99+
pass
100+
101+
def validate(self, helper: AbstractIntegrationTestHelper):
102+
"""
103+
Validate the test case using the given helper.
104+
"""
105+
pass

tests_integration/definitions/conda_forge_pinning/__init__.py renamed to tests_integration/lib/_definitions/conda_forge_pinning/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22

33
from fastapi import APIRouter
44

5-
from tests_integration.lib import IntegrationTestHelper, TestCase
5+
from ..base_classes import AbstractIntegrationTestHelper, TestCase
66

77

88
class SetupPinnings(TestCase):
99
def get_router(self) -> APIRouter:
1010
return APIRouter()
1111

12-
def prepare(self, helper: IntegrationTestHelper):
12+
def prepare(self, helper: AbstractIntegrationTestHelper):
1313
feedstock_dir = Path(__file__).parent / "resources" / "feedstock"
1414
helper.overwrite_feedstock_contents("conda-forge-pinning", feedstock_dir)
1515

16-
def validate(self, helper: IntegrationTestHelper):
16+
def validate(self, helper: AbstractIntegrationTestHelper):
1717
pass
1818

1919

tests_integration/definitions/pydantic/__init__.py renamed to tests_integration/lib/_definitions/pydantic/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from fastapi import APIRouter
55

6-
from tests_integration.lib import IntegrationTestHelper, TestCase
6+
from ..base_classes import AbstractIntegrationTestHelper, TestCase
77

88
PYPI_SIMPLE_API_RESPONSE = json.loads(
99
Path(__file__)
@@ -25,14 +25,14 @@ def handle_pypi_json_api():
2525

2626
return router
2727

28-
def prepare(self, helper: IntegrationTestHelper):
28+
def prepare(self, helper: AbstractIntegrationTestHelper):
2929
feedstock_dir = Path(__file__).parent / "resources" / "feedstock"
3030
helper.overwrite_feedstock_contents("pydantic", feedstock_dir)
3131

3232
feedstock_v1_dir = Path(__file__).parent / "resources" / "feedstock_v1"
3333
helper.overwrite_feedstock_contents("pydantic", feedstock_v1_dir, branch="1.x")
3434

35-
def validate(self, helper: IntegrationTestHelper):
35+
def validate(self, helper: AbstractIntegrationTestHelper):
3636
helper.assert_version_pr_present(
3737
"pydantic",
3838
new_version="2.10.2",

0 commit comments

Comments
 (0)