mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-23 15:18:14 +00:00
Compare commits
2 Commits
gl/feat/na
...
lg-fix-env
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
714d9d01a1 | ||
|
|
0ff0257d98 |
@@ -252,7 +252,7 @@ def write_env_file(folder_path, env_vars):
|
|||||||
env_file_path = folder_path / ".env"
|
env_file_path = folder_path / ".env"
|
||||||
with open(env_file_path, "w") as file:
|
with open(env_file_path, "w") as file:
|
||||||
for key, value in env_vars.items():
|
for key, value in env_vars.items():
|
||||||
file.write(f"{key}={value}\n")
|
file.write(f"{key.upper()}={value}\n")
|
||||||
|
|
||||||
|
|
||||||
def get_crews(crew_path: str = "crew.py", require: bool = False) -> list[Crew]:
|
def get_crews(crew_path: str = "crew.py", require: bool = False) -> list[Crew]:
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from click.testing import CliRunner
|
|||||||
|
|
||||||
from crewai.cli.create_crew import create_crew, create_folder_structure
|
from crewai.cli.create_crew import create_crew, create_folder_structure
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def runner():
|
def runner():
|
||||||
return CliRunner()
|
return CliRunner()
|
||||||
@@ -25,7 +24,7 @@ def temp_dir():
|
|||||||
def test_create_folder_structure_strips_single_trailing_slash():
|
def test_create_folder_structure_strips_single_trailing_slash():
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
folder_path, folder_name, class_name = create_folder_structure("hello/", parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure("hello/", parent_folder=temp_dir)
|
||||||
|
|
||||||
assert folder_name == "hello"
|
assert folder_name == "hello"
|
||||||
assert class_name == "Hello"
|
assert class_name == "Hello"
|
||||||
assert folder_path.name == "hello"
|
assert folder_path.name == "hello"
|
||||||
@@ -36,7 +35,7 @@ def test_create_folder_structure_strips_single_trailing_slash():
|
|||||||
def test_create_folder_structure_strips_multiple_trailing_slashes():
|
def test_create_folder_structure_strips_multiple_trailing_slashes():
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
folder_path, folder_name, class_name = create_folder_structure("hello///", parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure("hello///", parent_folder=temp_dir)
|
||||||
|
|
||||||
assert folder_name == "hello"
|
assert folder_name == "hello"
|
||||||
assert class_name == "Hello"
|
assert class_name == "Hello"
|
||||||
assert folder_path.name == "hello"
|
assert folder_path.name == "hello"
|
||||||
@@ -47,7 +46,7 @@ def test_create_folder_structure_strips_multiple_trailing_slashes():
|
|||||||
def test_create_folder_structure_handles_complex_name_with_trailing_slash():
|
def test_create_folder_structure_handles_complex_name_with_trailing_slash():
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
folder_path, folder_name, class_name = create_folder_structure("my-awesome_project/", parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure("my-awesome_project/", parent_folder=temp_dir)
|
||||||
|
|
||||||
assert folder_name == "my_awesome_project"
|
assert folder_name == "my_awesome_project"
|
||||||
assert class_name == "MyAwesomeProject"
|
assert class_name == "MyAwesomeProject"
|
||||||
assert folder_path.name == "my_awesome_project"
|
assert folder_path.name == "my_awesome_project"
|
||||||
@@ -58,7 +57,7 @@ def test_create_folder_structure_handles_complex_name_with_trailing_slash():
|
|||||||
def test_create_folder_structure_normal_name_unchanged():
|
def test_create_folder_structure_normal_name_unchanged():
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
folder_path, folder_name, class_name = create_folder_structure("hello", parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure("hello", parent_folder=temp_dir)
|
||||||
|
|
||||||
assert folder_name == "hello"
|
assert folder_name == "hello"
|
||||||
assert class_name == "Hello"
|
assert class_name == "Hello"
|
||||||
assert folder_path.name == "hello"
|
assert folder_path.name == "hello"
|
||||||
@@ -73,9 +72,9 @@ def test_create_folder_structure_with_parent_folder():
|
|||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
parent_path = Path(temp_dir) / "parent"
|
parent_path = Path(temp_dir) / "parent"
|
||||||
parent_path.mkdir()
|
parent_path.mkdir()
|
||||||
|
|
||||||
folder_path, folder_name, class_name = create_folder_structure("child/", parent_folder=parent_path)
|
folder_path, folder_name, class_name = create_folder_structure("child/", parent_folder=parent_path)
|
||||||
|
|
||||||
assert folder_name == "child"
|
assert folder_name == "child"
|
||||||
assert class_name == "Child"
|
assert class_name == "Child"
|
||||||
assert folder_path.name == "child"
|
assert folder_path.name == "child"
|
||||||
@@ -88,18 +87,18 @@ def test_create_folder_structure_with_parent_folder():
|
|||||||
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
||||||
def test_create_crew_with_trailing_slash_creates_valid_project(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
def test_create_crew_with_trailing_slash_creates_valid_project(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
||||||
mock_load_env.return_value = {}
|
mock_load_env.return_value = {}
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as work_dir:
|
with tempfile.TemporaryDirectory() as work_dir:
|
||||||
with mock.patch("crewai.cli.create_crew.create_folder_structure") as mock_create_folder:
|
with mock.patch("crewai.cli.create_crew.create_folder_structure") as mock_create_folder:
|
||||||
mock_folder_path = Path(work_dir) / "test_project"
|
mock_folder_path = Path(work_dir) / "test_project"
|
||||||
mock_create_folder.return_value = (mock_folder_path, "test_project", "TestProject")
|
mock_create_folder.return_value = (mock_folder_path, "test_project", "TestProject")
|
||||||
|
|
||||||
create_crew("test-project/", skip_provider=True)
|
create_crew("test-project/", skip_provider=True)
|
||||||
|
|
||||||
mock_create_folder.assert_called_once_with("test-project/", None)
|
mock_create_folder.assert_called_once_with("test-project/", None)
|
||||||
mock_copy_template.assert_called()
|
mock_copy_template.assert_called()
|
||||||
copy_calls = mock_copy_template.call_args_list
|
copy_calls = mock_copy_template.call_args_list
|
||||||
|
|
||||||
for call in copy_calls:
|
for call in copy_calls:
|
||||||
args = call[0]
|
args = call[0]
|
||||||
if len(args) >= 5:
|
if len(args) >= 5:
|
||||||
@@ -112,14 +111,14 @@ def test_create_crew_with_trailing_slash_creates_valid_project(mock_load_env, mo
|
|||||||
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
||||||
def test_create_crew_with_multiple_trailing_slashes(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
def test_create_crew_with_multiple_trailing_slashes(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
||||||
mock_load_env.return_value = {}
|
mock_load_env.return_value = {}
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as work_dir:
|
with tempfile.TemporaryDirectory() as work_dir:
|
||||||
with mock.patch("crewai.cli.create_crew.create_folder_structure") as mock_create_folder:
|
with mock.patch("crewai.cli.create_crew.create_folder_structure") as mock_create_folder:
|
||||||
mock_folder_path = Path(work_dir) / "test_project"
|
mock_folder_path = Path(work_dir) / "test_project"
|
||||||
mock_create_folder.return_value = (mock_folder_path, "test_project", "TestProject")
|
mock_create_folder.return_value = (mock_folder_path, "test_project", "TestProject")
|
||||||
|
|
||||||
create_crew("test-project///", skip_provider=True)
|
create_crew("test-project///", skip_provider=True)
|
||||||
|
|
||||||
mock_create_folder.assert_called_once_with("test-project///", None)
|
mock_create_folder.assert_called_once_with("test-project///", None)
|
||||||
|
|
||||||
|
|
||||||
@@ -128,21 +127,21 @@ def test_create_crew_with_multiple_trailing_slashes(mock_load_env, mock_write_en
|
|||||||
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
||||||
def test_create_crew_normal_name_still_works(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
def test_create_crew_normal_name_still_works(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
||||||
mock_load_env.return_value = {}
|
mock_load_env.return_value = {}
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as work_dir:
|
with tempfile.TemporaryDirectory() as work_dir:
|
||||||
with mock.patch("crewai.cli.create_crew.create_folder_structure") as mock_create_folder:
|
with mock.patch("crewai.cli.create_crew.create_folder_structure") as mock_create_folder:
|
||||||
mock_folder_path = Path(work_dir) / "normal_project"
|
mock_folder_path = Path(work_dir) / "normal_project"
|
||||||
mock_create_folder.return_value = (mock_folder_path, "normal_project", "NormalProject")
|
mock_create_folder.return_value = (mock_folder_path, "normal_project", "NormalProject")
|
||||||
|
|
||||||
create_crew("normal-project", skip_provider=True)
|
create_crew("normal-project", skip_provider=True)
|
||||||
|
|
||||||
mock_create_folder.assert_called_once_with("normal-project", None)
|
mock_create_folder.assert_called_once_with("normal-project", None)
|
||||||
|
|
||||||
|
|
||||||
def test_create_folder_structure_handles_spaces_and_dashes_with_slash():
|
def test_create_folder_structure_handles_spaces_and_dashes_with_slash():
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
folder_path, folder_name, class_name = create_folder_structure("My Cool-Project/", parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure("My Cool-Project/", parent_folder=temp_dir)
|
||||||
|
|
||||||
assert folder_name == "my_cool_project"
|
assert folder_name == "my_cool_project"
|
||||||
assert class_name == "MyCoolProject"
|
assert class_name == "MyCoolProject"
|
||||||
assert folder_path.name == "my_cool_project"
|
assert folder_path.name == "my_cool_project"
|
||||||
@@ -155,7 +154,7 @@ def test_create_folder_structure_raises_error_for_invalid_names():
|
|||||||
invalid_cases = [
|
invalid_cases = [
|
||||||
("123project/", "cannot start with a digit"),
|
("123project/", "cannot start with a digit"),
|
||||||
("True/", "reserved Python keyword"),
|
("True/", "reserved Python keyword"),
|
||||||
("False/", "reserved Python keyword"),
|
("False/", "reserved Python keyword"),
|
||||||
("None/", "reserved Python keyword"),
|
("None/", "reserved Python keyword"),
|
||||||
("class/", "reserved Python keyword"),
|
("class/", "reserved Python keyword"),
|
||||||
("def/", "reserved Python keyword"),
|
("def/", "reserved Python keyword"),
|
||||||
@@ -163,7 +162,7 @@ def test_create_folder_structure_raises_error_for_invalid_names():
|
|||||||
("", "empty or contain only whitespace"),
|
("", "empty or contain only whitespace"),
|
||||||
("@#$/", "contains no valid characters"),
|
("@#$/", "contains no valid characters"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for invalid_name, expected_error in invalid_cases:
|
for invalid_name, expected_error in invalid_cases:
|
||||||
with pytest.raises(ValueError, match=expected_error):
|
with pytest.raises(ValueError, match=expected_error):
|
||||||
create_folder_structure(invalid_name, parent_folder=temp_dir)
|
create_folder_structure(invalid_name, parent_folder=temp_dir)
|
||||||
@@ -179,20 +178,20 @@ def test_create_folder_structure_validates_names():
|
|||||||
("hello.world/", "helloworld", "HelloWorld"),
|
("hello.world/", "helloworld", "HelloWorld"),
|
||||||
("hello@world/", "helloworld", "HelloWorld"),
|
("hello@world/", "helloworld", "HelloWorld"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for valid_name, expected_folder, expected_class in valid_cases:
|
for valid_name, expected_folder, expected_class in valid_cases:
|
||||||
folder_path, folder_name, class_name = create_folder_structure(valid_name, parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure(valid_name, parent_folder=temp_dir)
|
||||||
assert folder_name == expected_folder
|
assert folder_name == expected_folder
|
||||||
assert class_name == expected_class
|
assert class_name == expected_class
|
||||||
|
|
||||||
assert folder_name.isidentifier(), f"folder_name '{folder_name}' should be valid Python identifier"
|
assert folder_name.isidentifier(), f"folder_name '{folder_name}' should be valid Python identifier"
|
||||||
assert not keyword.iskeyword(folder_name), f"folder_name '{folder_name}' should not be Python keyword"
|
assert not keyword.iskeyword(folder_name), f"folder_name '{folder_name}' should not be Python keyword"
|
||||||
assert not folder_name[0].isdigit(), f"folder_name '{folder_name}' should not start with digit"
|
assert not folder_name[0].isdigit(), f"folder_name '{folder_name}' should not start with digit"
|
||||||
|
|
||||||
assert class_name.isidentifier(), f"class_name '{class_name}' should be valid Python identifier"
|
assert class_name.isidentifier(), f"class_name '{class_name}' should be valid Python identifier"
|
||||||
assert not keyword.iskeyword(class_name), f"class_name '{class_name}' should not be Python keyword"
|
assert not keyword.iskeyword(class_name), f"class_name '{class_name}' should not be Python keyword"
|
||||||
assert folder_path.parent == Path(temp_dir)
|
assert folder_path.parent == Path(temp_dir)
|
||||||
|
|
||||||
if folder_path.exists():
|
if folder_path.exists():
|
||||||
shutil.rmtree(folder_path)
|
shutil.rmtree(folder_path)
|
||||||
|
|
||||||
@@ -202,13 +201,13 @@ def test_create_folder_structure_validates_names():
|
|||||||
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
||||||
def test_create_crew_with_parent_folder_and_trailing_slash(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
def test_create_crew_with_parent_folder_and_trailing_slash(mock_load_env, mock_write_env, mock_copy_template, temp_dir):
|
||||||
mock_load_env.return_value = {}
|
mock_load_env.return_value = {}
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as work_dir:
|
with tempfile.TemporaryDirectory() as work_dir:
|
||||||
parent_path = Path(work_dir) / "parent"
|
parent_path = Path(work_dir) / "parent"
|
||||||
parent_path.mkdir()
|
parent_path.mkdir()
|
||||||
|
|
||||||
create_crew("child-crew/", skip_provider=True, parent_folder=parent_path)
|
create_crew("child-crew/", skip_provider=True, parent_folder=parent_path)
|
||||||
|
|
||||||
crew_path = parent_path / "child_crew"
|
crew_path = parent_path / "child_crew"
|
||||||
assert crew_path.exists()
|
assert crew_path.exists()
|
||||||
assert not (crew_path / "src").exists()
|
assert not (crew_path / "src").exists()
|
||||||
@@ -224,23 +223,56 @@ def test_create_folder_structure_folder_name_validation():
|
|||||||
("for/", "reserved Python keyword"),
|
("for/", "reserved Python keyword"),
|
||||||
("@#$invalid/", "contains no valid characters.*Python module name"),
|
("@#$invalid/", "contains no valid characters.*Python module name"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for invalid_name, expected_error in folder_invalid_cases:
|
for invalid_name, expected_error in folder_invalid_cases:
|
||||||
with pytest.raises(ValueError, match=expected_error):
|
with pytest.raises(ValueError, match=expected_error):
|
||||||
create_folder_structure(invalid_name, parent_folder=temp_dir)
|
create_folder_structure(invalid_name, parent_folder=temp_dir)
|
||||||
|
|
||||||
valid_cases = [
|
valid_cases = [
|
||||||
("hello-world/", "hello_world"),
|
("hello-world/", "hello_world"),
|
||||||
("my.project/", "myproject"),
|
("my.project/", "myproject"),
|
||||||
("test@123/", "test123"),
|
("test@123/", "test123"),
|
||||||
("valid_name/", "valid_name"),
|
("valid_name/", "valid_name"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for valid_name, expected_folder in valid_cases:
|
for valid_name, expected_folder in valid_cases:
|
||||||
folder_path, folder_name, class_name = create_folder_structure(valid_name, parent_folder=temp_dir)
|
folder_path, folder_name, class_name = create_folder_structure(valid_name, parent_folder=temp_dir)
|
||||||
assert folder_name == expected_folder
|
assert folder_name == expected_folder
|
||||||
assert folder_name.isidentifier()
|
assert folder_name.isidentifier()
|
||||||
assert not keyword.iskeyword(folder_name)
|
assert not keyword.iskeyword(folder_name)
|
||||||
|
|
||||||
if folder_path.exists():
|
if folder_path.exists():
|
||||||
shutil.rmtree(folder_path)
|
shutil.rmtree(folder_path)
|
||||||
|
|
||||||
|
@mock.patch("crewai.cli.create_crew.create_folder_structure")
|
||||||
|
@mock.patch("crewai.cli.create_crew.copy_template")
|
||||||
|
@mock.patch("crewai.cli.create_crew.load_env_vars")
|
||||||
|
@mock.patch("crewai.cli.create_crew.get_provider_data")
|
||||||
|
@mock.patch("crewai.cli.create_crew.select_provider")
|
||||||
|
@mock.patch("crewai.cli.create_crew.select_model")
|
||||||
|
@mock.patch("click.prompt")
|
||||||
|
def test_env_vars_are_uppercased_in_env_file(
|
||||||
|
mock_prompt,
|
||||||
|
mock_select_model,
|
||||||
|
mock_select_provider,
|
||||||
|
mock_get_provider_data,
|
||||||
|
mock_load_env_vars,
|
||||||
|
mock_copy_template,
|
||||||
|
mock_create_folder_structure,
|
||||||
|
tmp_path
|
||||||
|
):
|
||||||
|
crew_path = tmp_path / "test_crew"
|
||||||
|
crew_path.mkdir()
|
||||||
|
mock_create_folder_structure.return_value = (crew_path, "test_crew", "TestCrew")
|
||||||
|
|
||||||
|
mock_load_env_vars.return_value = {}
|
||||||
|
mock_get_provider_data.return_value = {"openai": ["gpt-4"]}
|
||||||
|
mock_select_provider.return_value = "azure"
|
||||||
|
mock_select_model.return_value = "azure/openai"
|
||||||
|
mock_prompt.return_value = "fake-api-key"
|
||||||
|
|
||||||
|
create_crew("Test Crew")
|
||||||
|
|
||||||
|
env_file_path = crew_path / ".env"
|
||||||
|
content = env_file_path.read_text()
|
||||||
|
assert "MODEL=" in content
|
||||||
Reference in New Issue
Block a user