feat: add tomli so we can support 3.10 (#1506)

* feat: add tomli so we can support 3.10

* feat: add validation for poetry data
This commit is contained in:
Eduardo Chiarotti
2024-10-25 10:33:21 -03:00
committed by GitHub
parent 201e652fa2
commit 4589d6fe9d
5 changed files with 35 additions and 29 deletions

View File

@@ -28,6 +28,7 @@ dependencies = [
"uv>=0.4.25", "uv>=0.4.25",
"tomli-w>=1.1.0", "tomli-w>=1.1.0",
"chromadb>=0.4.24", "chromadb>=0.4.24",
"tomli>=2.0.2",
] ]
[project.urls] [project.urls]

View File

@@ -1,10 +1,9 @@
import subprocess import subprocess
import click import click
import tomllib
from packaging import version from packaging import version
from crewai.cli.utils import get_crewai_version from crewai.cli.utils import get_crewai_version, read_toml
def run_crew() -> None: def run_crew() -> None:
@@ -15,10 +14,9 @@ def run_crew() -> None:
crewai_version = get_crewai_version() crewai_version = get_crewai_version()
min_required_version = "0.71.0" min_required_version = "0.71.0"
with open("pyproject.toml", "rb") as f: pyproject_data = read_toml()
data = tomllib.load(f)
if data.get("tool", {}).get("poetry") and ( if pyproject_data.get("tool", {}).get("poetry") and (
version.parse(crewai_version) < version.parse(min_required_version) version.parse(crewai_version) < version.parse(min_required_version)
): ):
click.secho( click.secho(
@@ -35,10 +33,7 @@ def run_crew() -> None:
click.echo(f"An error occurred while running the crew: {e}", err=True) click.echo(f"An error occurred while running the crew: {e}", err=True)
click.echo(e.output, err=True, nl=True) click.echo(e.output, err=True, nl=True)
with open("pyproject.toml", "rb") as f: if pyproject_data.get("tool", {}).get("poetry"):
data = tomllib.load(f)
if data.get("tool", {}).get("poetry"):
click.secho( click.secho(
"It's possible that you are using an old version of crewAI that uses poetry, please run `crewai update` to update your pyproject.toml to use uv.", "It's possible that you are using an old version of crewAI that uses poetry, please run `crewai update` to update your pyproject.toml to use uv.",
fg="yellow", fg="yellow",

View File

@@ -2,7 +2,8 @@ import os
import shutil import shutil
import tomli_w import tomli_w
import tomllib
from crewai.cli.utils import read_toml
def update_crew() -> None: def update_crew() -> None:
@@ -18,10 +19,9 @@ def migrate_pyproject(input_file, output_file):
And it will be used to migrate the pyproject.toml to the new format when uv is used. And it will be used to migrate the pyproject.toml to the new format when uv is used.
When the time comes that uv supports the new format, this function will be deprecated. When the time comes that uv supports the new format, this function will be deprecated.
""" """
poetry_data = {}
# Read the input pyproject.toml # Read the input pyproject.toml
with open(input_file, "rb") as f: pyproject_data = read_toml()
pyproject = tomllib.load(f)
# Initialize the new project structure # Initialize the new project structure
new_pyproject = { new_pyproject = {
@@ -30,30 +30,30 @@ def migrate_pyproject(input_file, output_file):
} }
# Migrate project metadata # Migrate project metadata
if "tool" in pyproject and "poetry" in pyproject["tool"]: if "tool" in pyproject_data and "poetry" in pyproject_data["tool"]:
poetry = pyproject["tool"]["poetry"] poetry_data = pyproject_data["tool"]["poetry"]
new_pyproject["project"]["name"] = poetry.get("name") new_pyproject["project"]["name"] = poetry_data.get("name")
new_pyproject["project"]["version"] = poetry.get("version") new_pyproject["project"]["version"] = poetry_data.get("version")
new_pyproject["project"]["description"] = poetry.get("description") new_pyproject["project"]["description"] = poetry_data.get("description")
new_pyproject["project"]["authors"] = [ new_pyproject["project"]["authors"] = [
{ {
"name": author.split("<")[0].strip(), "name": author.split("<")[0].strip(),
"email": author.split("<")[1].strip(">").strip(), "email": author.split("<")[1].strip(">").strip(),
} }
for author in poetry.get("authors", []) for author in poetry_data.get("authors", [])
] ]
new_pyproject["project"]["requires-python"] = poetry.get("python") new_pyproject["project"]["requires-python"] = poetry_data.get("python")
else: else:
# If it's already in the new format, just copy the project section # If it's already in the new format, just copy the project section
new_pyproject["project"] = pyproject.get("project", {}) new_pyproject["project"] = pyproject_data.get("project", {})
# Migrate or copy dependencies # Migrate or copy dependencies
if "dependencies" in new_pyproject["project"]: if "dependencies" in new_pyproject["project"]:
# If dependencies are already in the new format, keep them as is # If dependencies are already in the new format, keep them as is
pass pass
elif "dependencies" in poetry: elif poetry_data and "dependencies" in poetry_data:
new_pyproject["project"]["dependencies"] = [] new_pyproject["project"]["dependencies"] = []
for dep, version in poetry["dependencies"].items(): for dep, version in poetry_data["dependencies"].items():
if isinstance(version, dict): # Handle extras if isinstance(version, dict): # Handle extras
extras = ",".join(version.get("extras", [])) extras = ",".join(version.get("extras", []))
new_dep = f"{dep}[{extras}]" new_dep = f"{dep}[{extras}]"
@@ -67,10 +67,10 @@ def migrate_pyproject(input_file, output_file):
new_pyproject["project"]["dependencies"].append(new_dep) new_pyproject["project"]["dependencies"].append(new_dep)
# Migrate or copy scripts # Migrate or copy scripts
if "scripts" in poetry: if poetry_data and "scripts" in poetry_data:
new_pyproject["project"]["scripts"] = poetry["scripts"] new_pyproject["project"]["scripts"] = poetry_data["scripts"]
elif "scripts" in pyproject.get("project", {}): elif pyproject_data.get("project", {}) and "scripts" in pyproject_data["project"]:
new_pyproject["project"]["scripts"] = pyproject["project"]["scripts"] new_pyproject["project"]["scripts"] = pyproject_data["project"]["scripts"]
else: else:
new_pyproject["project"]["scripts"] = {} new_pyproject["project"]["scripts"] = {}
@@ -87,8 +87,8 @@ def migrate_pyproject(input_file, output_file):
new_pyproject["project"]["scripts"]["run_crew"] = f"{module_name}.main:run" new_pyproject["project"]["scripts"]["run_crew"] = f"{module_name}.main:run"
# Migrate optional dependencies # Migrate optional dependencies
if "extras" in poetry: if poetry_data and "extras" in poetry_data:
new_pyproject["project"]["optional-dependencies"] = poetry["extras"] new_pyproject["project"]["optional-dependencies"] = poetry_data["extras"]
# Backup the old pyproject.toml # Backup the old pyproject.toml
backup_file = "pyproject-old.toml" backup_file = "pyproject-old.toml"

View File

@@ -6,6 +6,7 @@ from functools import reduce
from typing import Any, Dict, List from typing import Any, Dict, List
import click import click
import tomli
from rich.console import Console from rich.console import Console
from crewai.cli.authentication.utils import TokenManager from crewai.cli.authentication.utils import TokenManager
@@ -54,6 +55,13 @@ def simple_toml_parser(content):
return result return result
def read_toml(file_path: str = "pyproject.toml"):
"""Read the content of a TOML file and return it as a dictionary."""
with open(file_path, "rb") as f:
toml_dict = tomli.load(f)
return toml_dict
def parse_toml(content): def parse_toml(content):
if sys.version_info >= (3, 11): if sys.version_info >= (3, 11):
return tomllib.loads(content) return tomllib.loads(content)

2
uv.lock generated
View File

@@ -625,6 +625,7 @@ dependencies = [
{ name = "python-dotenv" }, { name = "python-dotenv" },
{ name = "pyvis" }, { name = "pyvis" },
{ name = "regex" }, { name = "regex" },
{ name = "tomli" },
{ name = "tomli-w" }, { name = "tomli-w" },
{ name = "uv" }, { name = "uv" },
] ]
@@ -679,6 +680,7 @@ requires-dist = [
{ name = "python-dotenv", specifier = ">=1.0.0" }, { name = "python-dotenv", specifier = ">=1.0.0" },
{ name = "pyvis", specifier = ">=0.3.2" }, { name = "pyvis", specifier = ">=0.3.2" },
{ name = "regex", specifier = ">=2024.9.11" }, { name = "regex", specifier = ">=2024.9.11" },
{ name = "tomli", specifier = ">=2.0.2" },
{ name = "tomli-w", specifier = ">=1.1.0" }, { name = "tomli-w", specifier = ">=1.1.0" },
{ name = "uv", specifier = ">=0.4.25" }, { name = "uv", specifier = ">=0.4.25" },
] ]