Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesigning protostar.toml 6 — Version checker #858

Merged
merged 6 commits into from
Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions protostar/configuration_file/configuration_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Any, Generic, Optional, TypeVar, Union

from protostar.protostar_exception import ProtostarException
from protostar.utils.protostar_directory import VersionType
from protostar.self import DeclaredProtostarVersionProviderProtocol, ProtostarVersion

PrimitiveTypesSupportedByConfigurationFile = Union[str, int, bool]

Expand Down Expand Up @@ -43,9 +43,11 @@ def create_file_content(
...


class ConfigurationFile(Generic[ConfigurationFileModelT]):
class ConfigurationFile(
DeclaredProtostarVersionProviderProtocol, Generic[ConfigurationFileModelT]
):
@abstractmethod
def get_min_protostar_version(self) -> Optional[VersionType]:
def get_declared_protostar_version(self) -> Optional[ProtostarVersion]:
...

@abstractmethod
Expand Down
12 changes: 6 additions & 6 deletions protostar/configuration_file/configuration_file_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pathlib import Path
from typing import Optional, Union

from protostar.utils.protostar_directory import VersionManager, VersionType
from protostar.self import ProtostarVersion, parse_protostar_version

from .configuration_file import (
CommandConfig,
Expand Down Expand Up @@ -47,15 +47,15 @@ def __init__(
"migrate",
]

def get_min_protostar_version(self) -> Optional[VersionType]:
def get_declared_protostar_version(self) -> Optional[ProtostarVersion]:
version_str = self._configuration_file_interpreter.get_attribute(
attribute_name="protostar_version",
section_name="config",
section_namespace="protostar",
)
if not version_str:
return None
return VersionManager.parse(version_str)
return parse_protostar_version(version_str)

def get_contract_names(self) -> list[str]:
contract_section = self._configuration_file_interpreter.get_section(
Expand Down Expand Up @@ -109,7 +109,7 @@ def read(
self,
) -> ConfigurationFileV1Model:
return ConfigurationFileV1Model(
protostar_version=self._get_min_protostar_version_str(),
protostar_version=self._get_declared_protostar_version_str(),
libs_path_str=self._get_libs_path_str(),
contract_name_to_path_strs=self._get_contract_name_to_path_strs(),
command_name_to_config=self._get_command_name_to_config(),
Expand All @@ -118,8 +118,8 @@ def read(
profile_name_to_shared_command_config=self._get_profile_name_to_shared_command_config(),
)

def _get_min_protostar_version_str(self) -> Optional[str]:
version = self.get_min_protostar_version()
def _get_declared_protostar_version_str(self) -> Optional[str]:
version = self.get_declared_protostar_version()
if not version:
return None
return str(version)
Expand Down
8 changes: 4 additions & 4 deletions protostar/configuration_file/configuration_file_v1_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from protostar.configuration_file.configuration_legacy_toml_interpreter import (
ConfigurationLegacyTOMLInterpreter,
)
from protostar.utils import VersionManager
from protostar.self import parse_protostar_version

from .configuration_file_v1 import (
ConfigurationFile,
Expand Down Expand Up @@ -56,10 +56,10 @@ def configuration_file_fixture(
""",
],
)
def test_retrieving_min_protostar_version(configuration_file: ConfigurationFile):
result = configuration_file.get_min_protostar_version()
def test_retrieving_declared_protostar_version(configuration_file: ConfigurationFile):
result = configuration_file.get_declared_protostar_version()

assert result == VersionManager.parse("0.1.2")
assert result == parse_protostar_version("0.1.2")


@pytest.mark.parametrize(
Expand Down
16 changes: 7 additions & 9 deletions protostar/configuration_file/configuration_file_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing_extensions import Self

from protostar.utils.protostar_directory import VersionManager, VersionType
from protostar.self import ProtostarVersion, parse_protostar_version

from .configuration_file import (
CommandConfig,
Expand All @@ -23,7 +23,7 @@

@dataclass
class ConfigurationFileV2Model:
min_protostar_version: Optional[str]
protostar_version: Optional[str]
contract_name_to_path_strs: dict[ContractName, list[str]]
project_config: CommandConfig
command_name_to_config: CommandNameToConfig
Expand All @@ -32,15 +32,15 @@ class ConfigurationFileV2Model:

@classmethod
# pylint: disable=invalid-name
def from_v1(cls, v1: ConfigurationFileV1Model, min_protostar_version: str) -> Self:
def from_v1(cls, v1: ConfigurationFileV1Model, protostar_version: str) -> Self:
project_config = v1.shared_command_config
if v1.libs_path_str:
project_config = {
**{"lib-path": v1.libs_path_str},
**v1.shared_command_config,
}
return cls(
min_protostar_version=min_protostar_version,
protostar_version=protostar_version,
contract_name_to_path_strs=v1.contract_name_to_path_strs,
command_name_to_config=v1.command_name_to_config,
profile_name_to_commands_config=v1.profile_name_to_commands_config,
Expand All @@ -64,13 +64,13 @@ def __init__(
self._configuration_file_reader = configuration_file_reader
self._filename = filename

def get_min_protostar_version(self) -> Optional[VersionType]:
def get_declared_protostar_version(self) -> Optional[ProtostarVersion]:
version_str = self._configuration_file_reader.get_attribute(
attribute_name="min-protostar-version", section_name="project"
)
if not version_str:
return None
return VersionManager.parse(version_str)
return parse_protostar_version(version_str)

def get_contract_names(self) -> list[str]:
contract_section = self._configuration_file_reader.get_section("contracts")
Expand Down Expand Up @@ -145,9 +145,7 @@ def create_file_content(
@staticmethod
def _prepare_project_section_data(model: ConfigurationFileV2Model) -> dict:
project_config_section = {}
project_config_section["min-protostar-version"] = str(
model.min_protostar_version
)
project_config_section["min-protostar-version"] = str(model.protostar_version)
project_config_section: dict = {
**project_config_section,
**model.project_config,
Expand Down
18 changes: 9 additions & 9 deletions protostar/configuration_file/configuration_file_v2_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from protostar.configuration_file.configuration_toml_interpreter import (
ConfigurationTOMLInterpreter,
)
from protostar.utils.protostar_directory import VersionManager
from protostar.self import parse_protostar_version

from .configuration_file import (
ConfigurationFile,
Expand Down Expand Up @@ -67,10 +67,10 @@ def configuration_file_fixture(project_root_path: Path, protostar_toml_content:
)


def test_retrieving_min_protostar_version(configuration_file: ConfigurationFile):
min_protostar_version = configuration_file.get_min_protostar_version()
def test_retrieving_declared_protostar_version(configuration_file: ConfigurationFile):
declared_protostar_version = configuration_file.get_declared_protostar_version()

assert min_protostar_version == VersionManager.parse("9.9.9")
assert declared_protostar_version == parse_protostar_version("9.9.9")


def test_retrieving_contract_names(configuration_file: ConfigurationFile):
Expand Down Expand Up @@ -122,7 +122,7 @@ def test_saving_configuration(
):
content_configurator = configuration_file
configuration_file_v2_model = ConfigurationFileV2Model(
min_protostar_version="9.9.9",
protostar_version="9.9.9",
project_config={
"lib-path": "lib",
"no-color": True,
Expand Down Expand Up @@ -163,10 +163,10 @@ def test_transforming_model_v1_into_v2():
profile_name_to_shared_command_config={"devnet": {"arg_name": 24}},
)

model_v2 = ConfigurationFileV2Model.from_v1(model_v1, min_protostar_version="0.4.0")
model_v2 = ConfigurationFileV2Model.from_v1(model_v1, protostar_version="0.4.0")

assert model_v2 == ConfigurationFileV2Model(
min_protostar_version="0.4.0",
protostar_version="0.4.0",
command_name_to_config={"deploy": {"arg_name": 21}},
contract_name_to_path_strs={"main": ["src/main.cairo"]},
project_config={"arg_name": 42, "lib-path": "lib"},
Expand Down Expand Up @@ -226,7 +226,7 @@ def test_transforming_file_v1_into_v2(protostar_toml_content: str):
filename="_",
).create_file_content(
content_builder=ConfigurationTOMLContentBuilder(),
model=ConfigurationFileV2Model.from_v1(model_v1, min_protostar_version="9.9.9"),
model=ConfigurationFileV2Model.from_v1(model_v1, protostar_version="9.9.9"),
)

assert transformed_protostar_toml == protostar_toml_content
Expand All @@ -237,7 +237,7 @@ def test_saving_in_particular_order(
):
content_configurator = configuration_file
configuration_file_v2_model = ConfigurationFileV2Model(
min_protostar_version="9.9.9",
protostar_version="9.9.9",
project_config={
"lib-path": "./lib",
"cairo-path": ["bar"],
Expand Down
5 changes: 5 additions & 0 deletions protostar/self/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .protostar_compatibility_with_project_checker import (
DeclaredProtostarVersionProviderProtocol,
ProtostarVersion,
parse_protostar_version,
)
56 changes: 56 additions & 0 deletions protostar/self/protostar_compatibility_with_project_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from enum import Enum, auto
from typing import Optional, Protocol

from packaging import version

ProtostarVersion = version.Version


class DeclaredProtostarVersionProviderProtocol(Protocol):
def get_declared_protostar_version(self) -> Optional[ProtostarVersion]:
...
mkaput marked this conversation as resolved.
Show resolved Hide resolved


class ProtostarVersionProviderProtocol(Protocol):
def get_protostar_version(self) -> ProtostarVersion:
...
kasperski95 marked this conversation as resolved.
Show resolved Hide resolved


class CompatibilityCheckResult(Enum):
COMPATIBLE = auto()
OUTDATED_PROTOSTAR = auto()
OUTDATED_DECLARED_VERSION = auto()
FAILURE = auto()


class ProtostarCompatibilityWithProjectChecker:
mkaput marked this conversation as resolved.
Show resolved Hide resolved
def __init__(
self,
protostar_version_provider: ProtostarVersionProviderProtocol,
declared_protostar_version_provider: DeclaredProtostarVersionProviderProtocol,
) -> None:
self._protostar_version_provider = protostar_version_provider
self._declared_protostar_version_provider = declared_protostar_version_provider

def check_compatibility(self) -> CompatibilityCheckResult:
protostar_version = self._protostar_version_provider.get_protostar_version()
declared_protostar_version = (
self._declared_protostar_version_provider.get_declared_protostar_version()
)
if declared_protostar_version is None:
return CompatibilityCheckResult.FAILURE
if (
declared_protostar_version.major == protostar_version.major
and declared_protostar_version.minor == protostar_version.minor
and declared_protostar_version.micro <= protostar_version.micro
):
return CompatibilityCheckResult.COMPATIBLE
if declared_protostar_version < protostar_version:
return CompatibilityCheckResult.OUTDATED_DECLARED_VERSION
return CompatibilityCheckResult.OUTDATED_PROTOSTAR


def parse_protostar_version(value: str) -> ProtostarVersion:
result = version.parse(value)
assert isinstance(result, ProtostarVersion)
return result
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import pytest

from .protostar_compatibility_with_project_checker import (
CompatibilityCheckResult,
DeclaredProtostarVersionProviderProtocol,
ProtostarCompatibilityWithProjectChecker,
ProtostarVersionProviderProtocol,
parse_protostar_version,
)


class DeclaredProtostarVersionProviderDouble(DeclaredProtostarVersionProviderProtocol):
def __init__(self, declared_protostar_version_str: str):
self._declared_protostar_version_str = declared_protostar_version_str

def get_declared_protostar_version(self):
return parse_protostar_version(self._declared_protostar_version_str)


class ProtostarVersionProviderDouble(ProtostarVersionProviderProtocol):
def __init__(self, protostar_version_str: str):
self._protostar_version_str = protostar_version_str

def get_protostar_version(self):
return parse_protostar_version(self._protostar_version_str)


@pytest.fixture(name="declared_protostar_version_provider")
def declared_protostar_version_provider_fixture(declared_protostar_version: str):
return DeclaredProtostarVersionProviderDouble(declared_protostar_version)


@pytest.fixture(name="protostar_version_provider")
def protostar_version_provider_fixture(protostar_version: str):
return ProtostarVersionProviderDouble(protostar_version)


@pytest.mark.parametrize(
"protostar_version, declared_protostar_version, is_compatible",
(
("0.1.2", "0.1.2", CompatibilityCheckResult.COMPATIBLE),
("0.1.2", "0.1.1", CompatibilityCheckResult.COMPATIBLE),
("1.0.0", "1.0.0", CompatibilityCheckResult.COMPATIBLE),
("0.1.1", "0.1.2", CompatibilityCheckResult.OUTDATED_PROTOSTAR),
("1.0.0", "1.1.0", CompatibilityCheckResult.OUTDATED_PROTOSTAR),
("0.2.0", "0.1.2", CompatibilityCheckResult.OUTDATED_DECLARED_VERSION),
("1.0.0", "0.9.0", CompatibilityCheckResult.OUTDATED_DECLARED_VERSION),
),
)
def test_compatibility(
declared_protostar_version_provider: DeclaredProtostarVersionProviderProtocol,
protostar_version_provider: ProtostarVersionProviderProtocol,
is_compatible: bool,
):
compatibility_checker = ProtostarCompatibilityWithProjectChecker(
protostar_version_provider,
declared_protostar_version_provider,
)

result = compatibility_checker.check_compatibility()

assert result == is_compatible