Add Python 3.10 support to CLI

This commit is contained in:
Thiago Moretto
2024-08-29 10:22:54 -03:00
parent d6034cebaa
commit b1ce3d57f0
2 changed files with 107 additions and 10 deletions

View File

@@ -1,11 +1,40 @@
import sys
import re import re
import subprocess import subprocess
import tomllib
from ..authentication.utils import TokenManager from ..authentication.utils import TokenManager
if sys.version_info >= (3, 11):
import tomllib
def simple_toml_parser(content):
result = {}
current_section = result
for line in content.split('\n'):
line = line.strip()
if line.startswith('[') and line.endswith(']'):
# New section
section = line[1:-1].split('.')
current_section = result
for key in section:
current_section = current_section.setdefault(key, {})
elif '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip().strip('"')
current_section[key] = value
return result
def parse_toml(content):
if sys.version_info >= (3, 11):
return tomllib.loads(content)
else:
return simple_toml_parser(content)
def get_git_remote_url() -> str: def get_git_remote_url() -> str:
"""Get the Git repository's remote URL.""" """Get the Git repository's remote URL."""
try: try:
@@ -37,7 +66,7 @@ def get_project_name(pyproject_path: str = "pyproject.toml"):
try: try:
# Read the pyproject.toml file # Read the pyproject.toml file
with open(pyproject_path, "rb") as f: with open(pyproject_path, "rb") as f:
pyproject_content = tomllib.load(f) pyproject_content = parse_toml(f.read())
# Extract the project name # Extract the project name
project_name = pyproject_content["tool"]["poetry"]["name"] project_name = pyproject_content["tool"]["poetry"]["name"]
@@ -51,8 +80,12 @@ def get_project_name(pyproject_path: str = "pyproject.toml"):
print(f"Error: {pyproject_path} not found.") print(f"Error: {pyproject_path} not found.")
except KeyError: except KeyError:
print(f"Error: {pyproject_path} is not a valid pyproject.toml file.") print(f"Error: {pyproject_path} is not a valid pyproject.toml file.")
except tomllib.TOMLDecodeError: except tomllib.TOMLDecodeError if sys.version_info >= (3, 11) else Exception as e:
print(f"Error: {pyproject_path} is not a valid TOML file.") print(
f"Error: {pyproject_path} is not a valid TOML file."
if sys.version_info >= (3, 11)
else f"Error reading the pyproject.toml file: {e}"
)
except Exception as e: except Exception as e:
print(f"Error reading the pyproject.toml file: {e}") print(f"Error reading the pyproject.toml file: {e}")
@@ -63,8 +96,8 @@ def get_crewai_version(pyproject_path: str = "pyproject.toml") -> str:
"""Get the version number of crewai from the pyproject.toml file.""" """Get the version number of crewai from the pyproject.toml file."""
try: try:
# Read the pyproject.toml file # Read the pyproject.toml file
with open("pyproject.toml", "rb") as f: with open(pyproject_path, "rb") as f:
pyproject_content = tomllib.load(f) pyproject_content = parse_toml(f.read())
# Extract the version number of crewai # Extract the version number of crewai
crewai_version = pyproject_content["tool"]["poetry"]["dependencies"]["crewai"][ crewai_version = pyproject_content["tool"]["poetry"]["dependencies"]["crewai"][
@@ -77,8 +110,12 @@ def get_crewai_version(pyproject_path: str = "pyproject.toml") -> str:
print(f"Error: {pyproject_path} not found.") print(f"Error: {pyproject_path} not found.")
except KeyError: except KeyError:
print(f"Error: {pyproject_path} is not a valid pyproject.toml file.") print(f"Error: {pyproject_path} is not a valid pyproject.toml file.")
except tomllib.TOMLDecodeError: except tomllib.TOMLDecodeError if sys.version_info >= (3, 11) else Exception as e:
print(f"Error: {pyproject_path} is not a valid TOML file.") print(
f"Error: {pyproject_path} is not a valid TOML file."
if sys.version_info >= (3, 11)
else f"Error reading the pyproject.toml file: {e}"
)
except Exception as e: except Exception as e:
print(f"Error reading the pyproject.toml file: {e}") print(f"Error reading the pyproject.toml file: {e}")

View File

@@ -1,9 +1,10 @@
import unittest import unittest
from io import StringIO from io import StringIO
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
import sys
from crewai.cli.deploy.main import DeployCommand from crewai.cli.deploy.main import DeployCommand
from crewai.cli.deploy.utils import parse_toml
class TestDeployCommand(unittest.TestCase): class TestDeployCommand(unittest.TestCase):
@patch("crewai.cli.deploy.main.get_auth_token") @patch("crewai.cli.deploy.main.get_auth_token")
@@ -151,3 +152,62 @@ class TestDeployCommand(unittest.TestCase):
self.assertIn( self.assertIn(
"Crew 'test_project' removed successfully", fake_out.getvalue() "Crew 'test_project' removed successfully", fake_out.getvalue()
) )
@patch('crewai.cli.deploy.utils.sys.version_info', (3, 10))
def test_parse_toml_python_310(self):
toml_content = """
[tool.poetry]
name = "test_project"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.10"
crewai = "^0.1.0"
"""
parsed = parse_toml(toml_content)
self.assertEqual(parsed['tool']['poetry']['name'], 'test_project')
self.assertEqual(parsed['tool']['poetry']['dependencies']['crewai'], '^0.1.0')
@unittest.skipIf(sys.version_info < (3, 11), "Requires Python 3.11+")
def test_parse_toml_python_311_plus(self):
toml_content = """
[tool.poetry]
name = "test_project"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.11"
crewai = "^0.1.0"
"""
parsed = parse_toml(toml_content)
self.assertEqual(parsed['tool']['poetry']['name'], 'test_project')
self.assertEqual(parsed['tool']['poetry']['dependencies']['crewai'], '^0.1.0')
@patch('builtins.open', new_callable=unittest.mock.mock_open, read_data="""
[tool.poetry]
name = "test_project"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.10"
crewai = "^0.1.0"
""")
def test_get_project_name_python_310(self, mock_open):
from crewai.cli.deploy.utils import get_project_name
project_name = get_project_name()
self.assertEqual(project_name, 'test_project')
@unittest.skipIf(sys.version_info < (3, 11), "Requires Python 3.11+")
@patch('builtins.open', new_callable=unittest.mock.mock_open, read_data="""
[tool.poetry]
name = "test_project"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.11"
crewai = "^0.1.0"
""")
def test_get_project_name_python_311_plus(self, mock_open):
from crewai.cli.deploy.utils import get_project_name
project_name = get_project_name()
self.assertEqual(project_name, 'test_project')