test: add default entries detection tests

This commit is contained in:
2023-03-23 22:30:19 +03:00
parent dd2aea32b8
commit eb50cb1c98
11 changed files with 136 additions and 37 deletions
+1
View File
@@ -0,0 +1 @@
from .logging import *
+2 -3
View File
@@ -13,14 +13,13 @@ logger = logging.getLogger("project")
class ProjectManager: class ProjectManager:
DEFAULT_PRESET = Path(__file__).parent / "default_preset.toml" DEFAULT_IGNORE = ["node_modules", ".venv", ".git", "tests"]
DEFAULT_IGNORE = ["node_modules", ".venv", ".git"]
_logger = logger _logger = logger
def __init__(self, basepath: Path): def __init__(self, basepath: Path):
self._basepaht = basepath self._basepaht = basepath
self._resolver = EntryResolver( self._resolver = EntryResolver(
PresetEntryDetector(self.DEFAULT_PRESET), PresetEntryDetector(),
self.DEFAULT_IGNORE, self.DEFAULT_IGNORE,
) )
+2
View File
@@ -67,6 +67,8 @@ class PipeRunner:
result = None result = None
for pipe in pipes: for pipe in pipes:
result = pipe.apply(result, self._basepath) result = pipe.apply(result, self._basepath)
if result is None:
break
return result return result
def resolve_value(self, pipeline: str) -> Any: def resolve_value(self, pipeline: str) -> Any:
+6 -2
View File
@@ -6,7 +6,11 @@ conditions = [
"file(pyproject.toml) | get(build-system.build-backend) | equal(poetry.core.masonry.api)", "file(pyproject.toml) | get(build-system.build-backend) | equal(poetry.core.masonry.api)",
] ]
variables.python_version = "file(pyproject.toml) | get(tool.poetry.dependencies.python) | search((\\d.\\d))" variables.python_version = "file(pyproject.toml) | get(tool.poetry.dependencies.python) | search((\\d.\\d))"
commands = ["poetry env use {python_version}", "poetry install"] commands = [
"poetry env use system",
"poetry env use {python_version}",
"poetry install",
]
[presets.python.tasks.build.poetry] [presets.python.tasks.build.poetry]
conditions = [ conditions = [
@@ -17,7 +21,7 @@ commands = ["poetry build"]
[presets.python.tasks.publish.poetry] [presets.python.tasks.publish.poetry]
conditions = [ conditions = [
"file(pyproject.toml) | get(build-system.build-backend) | equal(poetry.core.masonry.api)", "file(pyproject.toml) | get(build-system.build-backend) | equal(poetry.core.masonry.api)",
"file(poetry.toml)", "file(poetry.toml) | get(repositories)",
] ]
variables.python_repository = "file(poetry.toml) | get(repositories) | key(0)" variables.python_repository = "file(poetry.toml) | get(repositories) | key(0)"
commands = ["poetry publish -r {python_repository}"] commands = ["poetry publish -r {python_repository}"]
+14 -11
View File
@@ -5,7 +5,7 @@ from typing import Optional
from ..entry import Entry, EntryDetector from ..entry import Entry, EntryDetector
from ..pipe.core import PipeParser, PipeRunner from ..pipe.core import PipeParser, PipeRunner
from .resolve import PresetResolver from .resolve import PresetResolver, PresetResolverConfig
__all__ = ("PresetEntryDetector",) __all__ = ("PresetEntryDetector",)
@@ -13,11 +13,12 @@ __all__ = ("PresetEntryDetector",)
class PresetEntryDetector(EntryDetector): class PresetEntryDetector(EntryDetector):
_PIPE_PARSER = PipeParser() _PIPE_PARSER = PipeParser()
def __init__(self, filename: Path): def __init__(self, preset_resolver_config: Optional[PresetResolverConfig] = None):
self._pipeparser = PipeParser() self._pipeparser = PipeParser()
self._preset_resolver_config = preset_resolver_config
def detect_entry(self, basepath: Path) -> Optional["Entry"]: def detect_entry(self, basepath: Path) -> Optional["Entry"]:
preset = PresetResolver(basepath).resolve_preset() preset = PresetResolver(basepath, self._preset_resolver_config).resolve_preset()
piperunner = PipeRunner(basepath) piperunner = PipeRunner(basepath)
tasks = defaultdict(list) tasks = defaultdict(list)
for preset_name, preset in preset.presets.items(): for preset_name, preset in preset.presets.items():
@@ -26,14 +27,16 @@ class PresetEntryDetector(EntryDetector):
for task_name, task_pack in preset.tasks.items(): for task_name, task_pack in preset.tasks.items():
for task_item_name, task in task_pack.items(): for task_item_name, task in task_pack.items():
if piperunner.check_conditions(task.conditions): if piperunner.check_conditions(task.conditions):
variables = ( variables = {
{ "entry_path": basepath,
k: piperunner.resolve_value(v) }
for k, v in task.variables.items() if task.variables:
} variables.update(
if task.variables {
else {} k: piperunner.resolve_value(v)
) for k, v in task.variables.items()
}
)
tasks[task_name] += [ tasks[task_name] += [
command.format(**variables) for command in task.commands command.format(**variables) for command in task.commands
] ]
+32 -18
View File
@@ -1,35 +1,49 @@
__all__ = ("PresetResolver",) from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Dict, Iterable from typing import Dict, Iterable, Optional
import tomli import tomli
from ..util import merge_dicts from ..util import merge_dicts
from .model import Preset from .model import Preset
__all__ = (
"PresetResolverConfig",
"PresetResolver",
)
@dataclass
class PresetResolverConfig:
deafult: bool = True
user: bool = True
project: bool = True
class PresetResolver: class PresetResolver:
_source_cache: Dict[Path, dict] = {} _source_cache: Dict[Path, dict] = {}
def __init__(self, basepath: Path): def __init__(self, basepath: Path, config: Optional[PresetResolverConfig] = None):
self._basepath = basepath self._basepath = basepath
self._config = config or PresetResolverConfig()
def iter_sources(self) -> Iterable[Path]: def iter_sources(self) -> Iterable[Path]:
for filepath in (Path(__file__).parent / "default").iterdir(): if self._config.deafult:
yield filepath for filepath in (Path(__file__).parent / "default").iterdir():
user_preset = Path.home() / ".preset.toml" yield filepath
if user_preset.exists(): if self._config.user:
yield user_preset user_preset = Path.home() / ".preset.toml"
projectpath = self._basepath if user_preset.exists():
while projectpath.exists(): yield user_preset
project_preset = projectpath / ".preset.toml" if self._config.project:
if project_preset.exists(): projectpath = self._basepath
yield project_preset while projectpath.exists():
if projectpath.parent == projectpath: project_preset = projectpath / ".preset.toml"
break if project_preset.exists():
projectpath = projectpath.parent yield project_preset
if projectpath.parent == projectpath:
break
projectpath = projectpath.parent
def resolve_preset(self) -> Preset: def resolve_preset(self) -> Preset:
result_preset_data = {} result_preset_data = {}
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "project-manager" name = "project-manager"
version = "0.1.1" version = "0.1.2"
description = "" description = ""
authors = ["shmyga <shmyga.z@gmail.com>"] authors = ["shmyga <shmyga.z@gmail.com>"]
readme = "README.md" readme = "README.md"
+11
View File
@@ -0,0 +1,11 @@
{
"name": "example",
"version": "0.1.0",
"description": "",
"scripts": {
"build": "echo build"
},
"devDependencies": {
"jest": "^29.2.2"
}
}
+2
View File
@@ -0,0 +1,2 @@
[virtualenvs]
in-project = true
+17
View File
@@ -0,0 +1,17 @@
[tool.poetry]
name = "example"
version = "0.1.0"
description = ""
authors = []
[tool.poetry.dependencies]
python = "^3.8"
[tool.poetry.group.dev.dependencies]
black = "^23.1.0"
pytest = "^7.2.2"
isort = "^5.12.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
+48 -2
View File
@@ -1,2 +1,48 @@
def test_entry(): import shutil
pass from pathlib import Path
from typing import Optional
import pytest
from project_manager.entry import Entry, EntryDetector
from project_manager.preset.entry import PresetEntryDetector
from project_manager.preset.resolve import PresetResolverConfig
@pytest.fixture
def preset_resolver_config():
return PresetResolverConfig(
user=False,
project=False,
)
@pytest.fixture
def entry_detector(preset_resolver_config: PresetResolverConfig):
return PresetEntryDetector(preset_resolver_config)
@pytest.fixture
def entry(entry_detector: EntryDetector, entry_path: Path, tmp_path: Path):
destination = shutil.copytree(entry_path, tmp_path / entry_path.name)
return entry_detector.detect_entry(destination)
@pytest.mark.parametrize("entry_path", [Path(__file__).parent / "python"])
def test_python_entry(entry: Optional[Entry], entry_detector: EntryDetector):
assert entry is not None
assert {"setup", "build"} == entry._tasks.keys()
entry.run_task("setup")
entry = entry_detector.detect_entry(entry._basepath)
assert entry is not None
assert {"setup", "build", "lint", "format", "test", "clean"} == entry._tasks.keys()
@pytest.mark.parametrize("entry_path", [Path(__file__).parent / "nodejs"])
def test_nodejs_entry(entry: Optional[Entry], entry_detector: EntryDetector):
assert entry is not None
assert {"setup", "build"} == entry._tasks.keys()
entry.run_task("setup")
entry = entry_detector.detect_entry(entry._basepath)
assert entry is not None
assert {"setup", "build", "test", "clean"} == entry._tasks.keys()