Skip to content

Move poetry specific to component #144

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

Merged
merged 14 commits into from
Jan 7, 2024
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
30 changes: 29 additions & 1 deletion components/polylith/poetry/commands/create_project.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from pathlib import Path
from typing import Union

from cleo.helpers import option
from poetry.console.commands.command import Command
from polylith import project
Expand All @@ -6,6 +9,31 @@
command_name = "poly create project"


pyproject_template = """\
[tool.poetry]
name = "{name}"
version = "0.1.0"
description = "{description}"
authors = {authors}
license = ""

packages = []

[tool.poetry.dependencies]
python = "{python_version}"

[tool.poetry.group.dev.dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
"""


def create_project(root: Path, _ns: str, name: str, description: Union[str, None]):
project.create_project(root, pyproject_template, name, description or "")


class CreateProjectCommand(Command):
name = command_name
description = "Creates a <comment>Polylith</> project."
Expand All @@ -22,6 +50,6 @@ class CreateProjectCommand(Command):
]

def handle(self) -> int:
create(self, project.create_project)
create(self, create_project)

return 0
58 changes: 13 additions & 45 deletions components/polylith/project/create.py
Original file line number Diff line number Diff line change
@@ -1,63 +1,31 @@
from pathlib import Path
from typing import Union

import tomlkit
from polylith import repo
from polylith.dirs import create_dir
from polylith.repo import projects_dir

template = """\
[tool.poetry]
name = "{name}"
version = "0.1.0"
description = "{description}"
authors = {authors}
license = ""

packages = []

[tool.poetry.dependencies]
python = "{python_version}"

[tool.poetry.group.dev.dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
"""


def get_workspace_toml(path: Path) -> dict:
with open(str(path / repo.default_toml), "r", errors="ignore") as f:
data: dict = tomlkit.loads(f.read())

return data


def create_project_toml(
name: str, template: str, workspace_toml: dict, description: str
) -> tomlkit.TOMLDocument:
authors = workspace_toml["tool"]["poetry"]["authors"]
python_version = workspace_toml["tool"]["poetry"]["dependencies"]["python"]

content = template.format(
name=name,
description=description,
authors=authors,
python_version=python_version,
)
def create_project_toml(template: str, template_data: dict) -> tomlkit.TOMLDocument:
content = template.format(**template_data)

return tomlkit.loads(content)


def create_project(
path: Path, _namespace: str, name: str, description: Union[str, None]
) -> None:
def create_project(path: Path, template: str, name: str, description: str) -> None:
d = create_dir(path, f"{projects_dir}/{name}")

workspace_toml = get_workspace_toml(path)
authors = repo.get_authors(path)
python_version = repo.get_python_version(path)

project_toml = create_project_toml(
name, template, workspace_toml, description or ""
template,
{
"name": name,
"description": description,
"authors": authors,
"python_version": python_version,
},
)

fullpath = d / repo.default_toml
Expand Down
24 changes: 19 additions & 5 deletions components/polylith/project/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@
from typing import List

import tomlkit
from polylith.repo import default_toml
from polylith import repo, workspace


def get_project_package_includes(data) -> List[dict]:
def transform_to_package(namespace: str, include: str) -> dict:
path, _separator, brick = str.partition(include, f"/{namespace}/")

return {"include": f"{namespace}/{brick}", "from": path}


def get_project_package_includes(namespace: str, data) -> List[dict]:
if repo.is_pep_621_ready(data):
includes = data["project"].get("includes", [])
return [transform_to_package(namespace, include) for include in includes]

return data["tool"]["poetry"].get("packages", [])


def get_project_name(data) -> str:
if repo.is_pep_621_ready(data):
return data["project"]["name"]

return data["tool"]["poetry"]["name"]


Expand All @@ -19,8 +32,8 @@ def get_toml(path: Path) -> tomlkit.TOMLDocument:


def get_project_files(root: Path) -> dict:
projects = sorted(root.glob(f"projects/**/{default_toml}"))
development = Path(root / default_toml)
projects = sorted(root.glob(f"projects/**/{repo.default_toml}"))
development = Path(root / repo.default_toml)

proj = {"projects": projects}
dev = {"development": [development]}
Expand All @@ -43,11 +56,12 @@ def get_toml_files(root: Path) -> List[dict]:

def get_packages_for_projects(root: Path) -> List[dict]:
tomls = get_toml_files(root)
namespace = workspace.parser.get_namespace_from_config(root)

return [
{
"name": get_project_name(d["toml"]),
"packages": get_project_package_includes(d["toml"]),
"packages": get_project_package_includes(namespace, d["toml"]),
"path": d["path"],
"type": d["type"],
}
Expand Down
5 changes: 5 additions & 0 deletions components/polylith/repo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
from polylith.repo.get import get_authors, get_python_version
from polylith.repo.repo import (
bases_dir,
components_dir,
default_toml,
development_dir,
get_workspace_root,
is_pep_621_ready,
projects_dir,
readme_file,
workspace_file,
)

__all__ = [
"get_authors",
"get_python_version",
"bases_dir",
"components_dir",
"default_toml",
"development_dir",
"get_workspace_root",
"is_pep_621_ready",
"projects_dir",
"readme_file",
"workspace_file",
Expand Down
31 changes: 31 additions & 0 deletions components/polylith/repo/get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from functools import lru_cache
from pathlib import Path

import tomlkit
from polylith.repo.repo import default_toml, is_pep_621_ready


@lru_cache
def get_pyproject_data(path: Path) -> tomlkit.TOMLDocument:
with open(str(path / default_toml), "r", errors="ignore") as f:
return tomlkit.loads(f.read())


def get_metadata_section(data: dict) -> dict:
return data["project"] if is_pep_621_ready(data) else data["tool"]["poetry"]


def get_authors(path: Path) -> list:
data = get_pyproject_data(path)
section = get_metadata_section(data)

return section.get("authors", [])


def get_python_version(path: Path) -> str:
data: dict = get_pyproject_data(path)

if is_pep_621_ready(data):
return data["project"].get("requires-python", "")

return data["tool"]["poetry"]["dependencies"]["python"]
7 changes: 7 additions & 0 deletions components/polylith/repo/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,10 @@ def get_workspace_root(cwd: Path) -> Path:
)

return root


def is_pep_621_ready(pyproject: dict) -> bool:
if pyproject.get("tool", {}).get("poetry") is not None:
return False

return pyproject.get("project", {}).get("name") is not None
35 changes: 34 additions & 1 deletion components/polylith/sync/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,36 @@ def to_package(namespace: str, brick: str, brick_path: str, theme: str) -> dict:
return {"include": f"{namespace}/{brick}", "from": folder}


def generate_updated_project(data: TOMLDocument, packages: List[dict]) -> str:
def copy_toml_data(data: TOMLDocument) -> dict:
original = tomlkit.dumps(data)
copy: dict = tomlkit.parse(original)

return copy


def generate_updated_pep_621_ready_project(
data: TOMLDocument, packages: List[dict]
) -> str:
copy = copy_toml_data(data)

if copy["project"].get("includes") is None:
copy["project"].add("includes", [])

for package in packages:
brick = package["include"]
relative_path = package.get("from", "")
include = Path(relative_path, brick).as_posix()

copy["project"]["includes"].append(include)

copy["project"]["includes"].multiline(True)

return tomlkit.dumps(copy)


def generate_updated_poetry_project(data: TOMLDocument, packages: List[dict]) -> str:
copy = copy_toml_data(data)

if copy["tool"]["poetry"].get("packages") is None:
copy["tool"]["poetry"].add("packages", [])

Expand All @@ -27,6 +53,13 @@ def generate_updated_project(data: TOMLDocument, packages: List[dict]) -> str:
return tomlkit.dumps(copy)


def generate_updated_project(data: TOMLDocument, packages: List[dict]) -> str:
if repo.is_pep_621_ready(data):
return generate_updated_pep_621_ready_project(data, packages)

return generate_updated_poetry_project(data, packages)


def to_packages(root: Path, namespace: str, diff: dict) -> List[dict]:
theme = workspace.parser.get_theme_from_config(root)

Expand Down
25 changes: 25 additions & 0 deletions development/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Development


## Build and install local version
Make sure to uninstall the properly installed version you have via Poetry:

``` shell
poetry self remove poetry-polylith-plugin
```

Build a wheel from your local folder:
``` shell
poetry build-project --directory projects/poetry_polylith_plugin
```

Install into the Poetry virtual environment (Mac OS X), with pip:
``` shell
~/Library/Application\ Support/pypoetry/venv/bin/pip install projects/poetry_polylith_plugin/dist/poetry_polylith_plugin-<INSERT-VERSION-HERE>-py3-none-any.whl
```

When done testing, don't forget to uninstall the local test version:
``` shell
~/Library/Application\ Support/pypoetry/venv/bin/pip uninstall poetry-polylith-plugin
```

2 changes: 1 addition & 1 deletion projects/poetry_polylith_plugin/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "poetry-polylith-plugin"
version = "1.12.2"
version = "1.13.0"
description = "A Poetry plugin that adds tooling support for the Polylith Architecture"
authors = ["David Vujic"]
homepage = "https://davidvujic.github.io/python-polylith-docs/"
Expand Down
22 changes: 22 additions & 0 deletions test/components/polylith/project/test_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import tomlkit
from polylith.project.create import create_project_toml


def test_create_project_toml():
name = "unit test project"
description = "this is a unit test"
authors = ["one", "two", "three"]
python_version = "something"

template = 'x = "{name}{description}{authors}{python_version}"'

data = {
"name": name,
"description": description,
"authors": authors,
"python_version": python_version,
}

res = create_project_toml(template, data)

assert tomlkit.dumps(res) == f'x = "{name}{description}{authors}{python_version}"'
34 changes: 34 additions & 0 deletions test/components/polylith/project/test_project_get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from polylith import project
import tomlkit

namespace = "unittest"

poetry_toml = """\
[tool.poetry]
packages = [
{include = "unittest/one",from = "../../components"}
]
"""


pep_621_toml = """\
[project]
name = "unit test"
includes = ["../../components/unittest/one"]
"""


def test_get_poetry_package_includes():
data = tomlkit.loads(poetry_toml)

res = project.get.get_project_package_includes(namespace, data)

assert res == [{"include": "unittest/one", "from": "../../components"}]


def test_get_pep_621_includes():
data = tomlkit.loads(pep_621_toml)

res = project.get.get_project_package_includes(namespace, data)

assert res == [{"include": "unittest/one", "from": "../../components"}]
Loading