Skip to content

Commit 71d593a

Browse files
committed
intermediate version
1 parent dfc241e commit 71d593a

10 files changed

Lines changed: 93 additions & 101 deletions

File tree

src/cpp_dev/project/dependency/__init__.py

Whitespace-only changes.

src/cpp_dev/project/management.py

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,23 @@
33
# This work is licensed under the terms of the BSD-3-Clause license.
44
# For a copy, see <https://opensource.org/license/bsd-3-clause>.
55

6+
from copy import deepcopy
67
from pathlib import Path
7-
from textwrap import dedent
88
from typing import get_args
99

10-
from cpp_dev.conan.package import compute_dependency_graph
10+
from cpp_dev.dependency.specifier import DependencySpecifier
1111

12-
from ..dependency.types import PackageDependency
13-
from .config import create_project_config, load_project_config, update_dependencies
14-
from .dependency.utils import refine_package_dependencies
15-
from .lockfile import create_initial_lock_file
16-
from .path_composition import compose_include_file, compose_source_file
12+
from .config import load_project_config, update_dependencies
1713
from .types import DependencyType, ProjectConfig
1814

1915
###############################################################################
2016
# Public API ###
2117
###############################################################################
2218

2319

24-
def add_package_dependency(project_dir: Path, deps: list[PackageDependency], dep_type: DependencyType) -> None:
20+
def add_package_dependency(project_dir: Path, deps: list[DependencySpecifier], dep_type: DependencyType) -> None:
2521
"""Add package dependencies to the project for the given type."""
26-
refined_deps = refine_package_dependencies(deps)
22+
refined_deps = _refine_package_dependencies(deps)
2723
project_config = load_project_config(project_dir)
2824
updated_config = update_dependencies(project_config, refined_deps, dep_type)
2925
_collect_dependency_graph(updated_config)
@@ -34,8 +30,35 @@ def add_package_dependency(project_dir: Path, deps: list[PackageDependency], dep
3430
###############################################################################
3531

3632

37-
def _collect_dependency_graph(project_config: ProjectConfig) -> None:
38-
all_package_deps = [
39-
dep for dep_type in get_args(DependencyType) for dep in project_config.get_dependencies(dep_type)
40-
]
41-
compute_dependency_graph(all_package_deps)
33+
def _collect_dependency_graph(project_config: ProjectConfig) -> None: ...
34+
35+
36+
DEFAULT_REPOSITORY = "official"
37+
38+
39+
def _refine_package_dependencies(deps: list[DependencySpecifier]) -> list[DependencySpecifier]:
40+
"""Refine the package dependencies in case of defaults were chosen.
41+
42+
The refinement includes (in order):
43+
o Default repository "official"
44+
o Latest resolved version in case of "latest"
45+
46+
This step is performed to assure that package dependencies with "latest" do not get an older version
47+
than the latest one at the time of resolution. This is important in case a versions gets removed.
48+
"""
49+
updated_deps = []
50+
for dep in deps:
51+
repository = dep.repository if dep.repository is not None else DEFAULT_REPOSITORY
52+
version_spec = dep.version_spec
53+
if dep.version_spec == "latest":
54+
available_versions = get_available_versions(dep.repository, dep.name)
55+
if len(available_versions) == 0:
56+
raise ValueError(f"No available versions for package {parts.name} at repository {parts.repository}.")
57+
parts.version_spec = [
58+
VersionSpecBound(
59+
operand=VersionSpecBoundOperand.GREATER_THAN_OR_EQUAL,
60+
version=SemanticVersionWithOptionalParts.from_semantic_version(available_versions[0]),
61+
)
62+
]
63+
updated_deps.append(PackageDependency.from_parts(parts))
64+
return updated_deps

src/cpp_dev/tool/init.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from filelock import FileLock, Timeout
1010

1111
from cpp_dev.common.utils import ensure_dir_exists
12-
from cpp_dev.dependency.conan.setup import initialize_conan
12+
from cpp_dev.dependency.conan.setup import get_conan_config_source_dir, initialize_conan
1313
from cpp_dev.tool.version import get_cpd_version_from_code, read_version_file, write_version_file
1414

1515
###############################################################################
@@ -91,7 +91,7 @@ def _initialize_cpd(cpd_dir: Path) -> None:
9191
def _initialize_conan(cpd_dir: Path) -> None:
9292
conan_dir = _compose_conan_home(cpd_dir)
9393
ensure_dir_exists(conan_dir)
94-
initialize_conan(conan_dir)
94+
initialize_conan(conan_dir, get_conan_config_source_dir())
9595
write_version_file(cpd_dir, get_cpd_version_from_code())
9696

9797

src/tests/cpp_dev/dependency/conan/conftest.py renamed to src/tests/cpp_dev/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@
1313
###############################################################################
1414
@pytest.fixture
1515
def unused_http_port() -> int:
16+
"""Return an unused HTTP port in a pre-defined range."""
1617
for port in range(50000, 50100):
1718
if not _is_port_in_use(port):
1819
return port
1920
raise RuntimeError("No unused HTTP port found")
2021

22+
2123
###############################################################################
2224
# Implementation ###
2325
###############################################################################
2426

27+
2528
def _is_port_in_use(port: int) -> bool:
2629
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
2730
return s.connect_ex(("localhost", port)) == 0

src/tests/cpp_dev/dependency/conan/test_command_wrapper.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from cpp_dev.dependency.conan.types import ConanPackageReference
2222
from cpp_dev.dependency.conan.utils import conan_env
2323

24-
from .utils.env import ConanTestEnv, create_conan_env
24+
from .utils.env import ConanTestEnv, ConanTestPackage, create_conan_test_env
2525
from .utils.server import ConanServer, launch_conan_test_server
2626

2727
MockType = MagicMock | AsyncMock
@@ -62,22 +62,29 @@ def test_conan_upload(patched_run_command_assert_success: MockType) -> None:
6262
str(package_ref),
6363
)
6464

65-
@dataclass
66-
class ConanTestEnvironment:
67-
server: ConanServer
68-
conan: ConanTestEnv
6965

7066
@pytest.fixture
71-
def conan_test_environment(tmp_path: Path, unused_http_port: int) -> Generator[ConanTestEnvironment]:
72-
with launch_conan_test_server(tmp_path / "server", unused_http_port) as server:
73-
with create_conan_env(tmp_path / "conan", server.http_port) as conan:
74-
conan.create_and_upload_package(ConanPackageReference("dep/1.0.0@official/cppdev"), [])
75-
conan.create_and_upload_package(ConanPackageReference("cpd1/1.0.0@official/cppdev"), [])
76-
conan.create_and_upload_package(ConanPackageReference("cpd/1.0.0@official/cppdev"), [ConanPackageReference("dep/1.0.0@official/cppdev")])
77-
yield ConanTestEnvironment(
78-
server=server,
79-
conan=conan,
80-
)
67+
def conan_test_environment(tmp_path: Path, unused_http_port: int) -> Generator[ConanTestEnv]:
68+
with launch_conan_test_server(tmp_path, unused_http_port) as server:
69+
TEST_PACKAGES = [
70+
ConanTestPackage(
71+
ref=ConanPackageReference("dep/1.0.0@official/cppdev"),
72+
dependencies=[],
73+
cpp_standard="c++17",
74+
),
75+
ConanTestPackage(
76+
ref=ConanPackageReference("cpd1/1.0.0@official/cppdev"),
77+
dependencies=[],
78+
cpp_standard="c++17",
79+
),
80+
ConanTestPackage(
81+
ref=ConanPackageReference("cpd/1.0.0@official/cppdev"),
82+
dependencies=[ConanPackageReference("dep/1.0.0@official/cppdev")],
83+
cpp_standard="c++17",
84+
),
85+
]
86+
with create_conan_test_env(tmp_path / "conan", server.http_port, TEST_PACKAGES) as conan_test_env:
87+
yield conan_test_env
8188

8289

8390
@pytest.mark.usefixtures("conan_test_environment")
@@ -87,15 +94,14 @@ def test_conan_list() -> None:
8794
assert ConanPackageReference("cpd/1.0.0@official/cppdev") in result
8895

8996

90-
@pytest.mark.usefixtures("conan_test_environment")
91-
def test_conan_graph_buildorder(tmp_path: Path, conan_test_environment: ConanTestEnvironment) -> None:
97+
def test_conan_graph_buildorder(tmp_path: Path, conan_test_environment: ConanTestEnv) -> None:
9298
conanfile_path = tmp_path / "conanfile.txt"
9399
conanfile_path.write_text(dedent("""
94100
[requires]
95101
cpd/1.0.0@official/cppdev
96102
""")
97103
)
98-
graph_build_order = conan_graph_buildorder(conanfile_path, conan_test_environment.conan.profile)
104+
graph_build_order = conan_graph_buildorder(conanfile_path, conan_test_environment.profile)
99105
assert len(graph_build_order.order) == 2
100106
assert len(graph_build_order.order[0]) == 1
101107
dep_recipe = graph_build_order.order[0][0]

src/tests/cpp_dev/dependency/conan/test_provider.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,37 @@
1313
from cpp_dev.dependency.conan.provider import ConanDependencyProvider
1414
from cpp_dev.dependency.conan.types import ConanPackageReference
1515
from tests.cpp_dev.dependency.conan.utils.env import (ConanTestEnv,
16-
create_conan_env)
16+
ConanTestPackage,
17+
create_conan_test_env)
1718
from tests.cpp_dev.dependency.conan.utils.server import (
1819
ConanServer, launch_conan_test_server)
1920

2021

21-
@dataclass
22-
class ConanTestEnvironment:
23-
server: ConanServer
24-
conan: ConanTestEnv
25-
26-
2722
@pytest.fixture
28-
def conan_test_environment(tmp_path: Path, unused_http_port: int) -> Generator[ConanTestEnvironment]:
29-
with launch_conan_test_server(tmp_path / "server", unused_http_port) as conan_server:
30-
with create_conan_env(tmp_path / "conan", conan_server.http_port) as conan_env:
31-
conan_env.create_and_upload_package(ConanPackageReference("cpd/1.0.0@official/cppdev"), [])
32-
conan_env.create_and_upload_package(ConanPackageReference("cpd/2.0.0@custom/cppdev"), [])
33-
conan_env.create_and_upload_package(ConanPackageReference("cpd/3.0.0@official/cppdev"), [])
34-
yield ConanTestEnvironment(
35-
server=conan_server,
36-
conan=conan_env
37-
)
38-
39-
40-
def test_get_available_versions(conan_test_environment: ConanTestEnvironment) -> None:
41-
provider = ConanDependencyProvider(conan_test_environment.conan.conan_dir)
23+
def conan_test_environment(tmp_path: Path, unused_http_port: int) -> Generator[ConanTestEnv]:
24+
TEST_PACKAGES = [
25+
ConanTestPackage(
26+
ref=ConanPackageReference("cpd/1.0.0@official/cppdev"),
27+
dependencies=[],
28+
cpp_standard="c++17",
29+
),
30+
ConanTestPackage(
31+
ref=ConanPackageReference("cpd/2.0.0@custom/cppdev"),
32+
dependencies=[],
33+
cpp_standard="c++17",
34+
),
35+
ConanTestPackage(
36+
ref=ConanPackageReference("cpd/3.0.0@official/cppdev"),
37+
dependencies=[],
38+
cpp_standard="c++17",
39+
),
40+
]
41+
with create_conan_test_env(tmp_path, unused_http_port, TEST_PACKAGES) as conan_test_env:
42+
yield conan_test_env
43+
44+
45+
def test_get_available_versions(conan_test_environment: ConanTestEnv) -> None:
46+
provider = ConanDependencyProvider(conan_test_environment.conan_home_dir)
4247
assert provider.fetch_versions("official", "cpd") == [
4348
SemanticVersion("3.0.0"),
4449
SemanticVersion("1.0.0"),

src/tests/cpp_dev/project/dependency/__init__.py

Whitespace-only changes.

src/tests/cpp_dev/project/dependency/_test_utils.py

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
@pytest.fixture(autouse=True)
1919
def conan_remote_login() -> object:
2020
"""Mock the conan user and password setting function."""
21-
with patch("cpp_dev.conan.setup.conan_remote_login", return_value=None) as mock:
21+
with patch("cpp_dev.dependency.conan.setup.conan_remote_login", return_value=None) as mock:
2222
yield mock
2323

2424

0 commit comments

Comments
 (0)