Fix venv files not being found (#525)
This commit is contained in:
parent
21f892c0a0
commit
7888dc505e
5 changed files with 34 additions and 91 deletions
|
|
@ -10,7 +10,7 @@ from typing import Any
|
|||
|
||||
import toml
|
||||
from arcade_core import Toolkit
|
||||
from arcade_core.toolkit import valid_path
|
||||
from arcade_core.toolkit import Validate
|
||||
from arcadepy import Arcade, NotFoundError
|
||||
from httpx import Client, ConnectError, HTTPStatusError, TimeoutException
|
||||
from packaging.requirements import Requirement
|
||||
|
|
@ -230,7 +230,7 @@ class Worker(BaseModel):
|
|||
|
||||
def exclude_filter(tarinfo: tarfile.TarInfo) -> tarfile.TarInfo | None:
|
||||
"""Filter for files/directories to exclude from the compressed package"""
|
||||
if not valid_path(tarinfo.name):
|
||||
if not Validate.path(tarinfo.name):
|
||||
return None
|
||||
|
||||
return tarinfo
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ class Toolkit(BaseModel):
|
|||
"""
|
||||
# Get all python files in the package directory
|
||||
try:
|
||||
modules = [f for f in package_dir.glob("**/*.py") if f.is_file() and valid_path(f)]
|
||||
modules = [f for f in package_dir.glob("**/*.py") if f.is_file() and Validate.path(f)]
|
||||
except OSError as e:
|
||||
raise ToolkitLoadError(
|
||||
f"Failed to locate Python files in package directory for '{package_name}'."
|
||||
|
|
@ -289,23 +289,30 @@ def get_package_directory(package_name: str) -> str:
|
|||
raise ImportError(f"Package {package_name} does not have a file path associated with it")
|
||||
|
||||
|
||||
def valid_path(path: str | Path) -> bool:
|
||||
"""
|
||||
Validate if a path is valid to be served or deployed.
|
||||
"""
|
||||
# Check both POSIX and Windows interpretations
|
||||
posix_path = PurePosixPath(path)
|
||||
windows_path = PureWindowsPath(path)
|
||||
class Validate:
|
||||
warn = True
|
||||
|
||||
# Get all possible parts from both interpretations
|
||||
all_parts = set(posix_path.parts) | set(windows_path.parts)
|
||||
@classmethod
|
||||
def path(cls, path: str | Path) -> bool:
|
||||
"""
|
||||
Validate if a path is valid to be served or deployed.
|
||||
"""
|
||||
# Check both POSIX and Windows interpretations
|
||||
posix_path = PurePosixPath(path)
|
||||
windows_path = PureWindowsPath(path)
|
||||
|
||||
for part in all_parts:
|
||||
if part.startswith("."):
|
||||
return False
|
||||
if part in {"dist", "build", "__pycache__", "venv", "coverage.xml"}:
|
||||
return False
|
||||
if part.endswith(".lock"):
|
||||
return False
|
||||
# Get all possible parts from both interpretations
|
||||
all_parts = set(posix_path.parts) | set(windows_path.parts)
|
||||
|
||||
return True
|
||||
for part in all_parts:
|
||||
if (part == "venv" or part.startswith(".")) and cls.warn:
|
||||
print(
|
||||
f"⚠️ Your package may contain a venv directory or hidden files. We suggest moving these out of the toolkit directory to avoid deployment issues: {path}"
|
||||
)
|
||||
cls.warn = False
|
||||
if part in {"dist", "build", "__pycache__", "coverage.xml"}:
|
||||
return False
|
||||
if part.endswith(".lock"):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "arcade-core"
|
||||
version = "2.2.1"
|
||||
version = "2.2.2"
|
||||
description = "Arcade Core - Core library for Arcade platform"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from unittest.mock import MagicMock, patch
|
|||
|
||||
import pytest
|
||||
from arcade_core.errors import ToolkitLoadError
|
||||
from arcade_core.toolkit import Toolkit, valid_path
|
||||
from arcade_core.toolkit import Toolkit, Validate
|
||||
|
||||
|
||||
class TestToolkit:
|
||||
|
|
@ -400,7 +400,7 @@ class TestValidateFile:
|
|||
|
||||
|
||||
class TestValidPath:
|
||||
"""Test the valid_path function for path validation during deployment and serving."""
|
||||
"""Test the Validate.path function for path validation during deployment and serving."""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path_input",
|
||||
|
|
@ -452,80 +452,25 @@ class TestValidPath:
|
|||
Path("file.py"),
|
||||
Path("src/module.py"),
|
||||
],
|
||||
ids=[
|
||||
"simple_file_py",
|
||||
"simple_module_py",
|
||||
"simple_utils_py",
|
||||
"simple_main_py",
|
||||
"simple_readme_md",
|
||||
"simple_config_json",
|
||||
"nested_src_main",
|
||||
"nested_lib_utils",
|
||||
"nested_package_subpackage",
|
||||
"nested_tools_scripts",
|
||||
"nested_docs_api",
|
||||
"nested_tests_unit",
|
||||
"deep_nested_very_deep",
|
||||
"deep_nested_a_b_c",
|
||||
"edge_case_empty_string",
|
||||
"edge_case_single_a",
|
||||
"edge_case_single_1",
|
||||
"contains_dist_but_valid",
|
||||
"contains_build_but_valid",
|
||||
"contains_lock_but_valid",
|
||||
"contains_unlock_valid",
|
||||
"case_sensitive_DIST",
|
||||
"case_sensitive_Build",
|
||||
"case_sensitive_VENV",
|
||||
"case_sensitive_LOCK",
|
||||
"windows_src_module",
|
||||
"windows_lib_utils",
|
||||
"absolute_home_user",
|
||||
"unicode_cyrillic",
|
||||
"unicode_chinese",
|
||||
"unicode_accented",
|
||||
"spaces_in_filename",
|
||||
"dashes_in_filename",
|
||||
"underscores_in_filename",
|
||||
"path_object_file",
|
||||
"path_object_nested",
|
||||
],
|
||||
)
|
||||
def test_valid_paths(self, path_input):
|
||||
"""Test that valid paths are accepted."""
|
||||
assert valid_path(path_input) is True
|
||||
assert Validate.path(path_input) is True
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"path_input",
|
||||
[
|
||||
# Hidden files (starting with .)
|
||||
".hidden",
|
||||
".gitignore",
|
||||
".env",
|
||||
".DS_Store",
|
||||
".vscode",
|
||||
".pytest_cache",
|
||||
# Paths containing hidden directories
|
||||
".hidden/file.py",
|
||||
"src/.cache/data.py",
|
||||
"lib/.git/config",
|
||||
".vscode/settings.json",
|
||||
"deep/.hidden/nested/file.py",
|
||||
"normal/.DS_Store",
|
||||
# Excluded directories (exact matches)
|
||||
"dist",
|
||||
"build",
|
||||
"__pycache__",
|
||||
"venv",
|
||||
"coverage.xml",
|
||||
# Paths containing excluded directories
|
||||
"dist/bundle.js",
|
||||
"build/output/file.py",
|
||||
"src/__pycache__/module.cpython-39.pyc",
|
||||
"venv/lib/python3.9/site-packages/module.py",
|
||||
"project/build/artifacts/file.py",
|
||||
"lib/dist/package/module.py",
|
||||
"tools/venv/bin/python",
|
||||
# Lock files (ending with .lock)
|
||||
"package.lock",
|
||||
"poetry.lock",
|
||||
|
|
@ -539,28 +484,19 @@ class TestValidPath:
|
|||
"frontend/yarn.lock",
|
||||
"backend/poetry.lock",
|
||||
"deep/nested/path/file.lock",
|
||||
# Multiple violations
|
||||
".hidden/dist/file.py", # hidden + excluded dir
|
||||
"build/.cache/file.py", # excluded dir + hidden
|
||||
"venv/package.lock", # excluded dir + lock file
|
||||
".git/hooks/file.lock", # hidden + lock file
|
||||
# Windows-style paths that should be invalid
|
||||
"dist\\bundle.js",
|
||||
".hidden\\file.py",
|
||||
"src\\package.lock",
|
||||
# Absolute paths that should be invalid
|
||||
"/home/user/project/.hidden/file.py",
|
||||
"/home/user/project/dist/file.py",
|
||||
"/opt/project/package.lock",
|
||||
# Unicode with exclusion patterns
|
||||
".файл", # Hidden Cyrillic file
|
||||
"文件.lock", # Chinese lock file
|
||||
# Path objects
|
||||
Path(".hidden/file.py"),
|
||||
Path("dist/bundle.js"),
|
||||
Path("package.lock"),
|
||||
],
|
||||
)
|
||||
def test_invalid_paths(self, path_input):
|
||||
"""Test that invalid paths are rejected."""
|
||||
assert valid_path(path_input) is False
|
||||
assert Validate.path(path_input) is False
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "arcade-ai"
|
||||
version = "2.1.3"
|
||||
version = "2.1.4"
|
||||
description = "Arcade.dev - Tool Calling platform for Agents"
|
||||
readme = "README.md"
|
||||
license = {file = "LICENSE"}
|
||||
|
|
@ -21,7 +21,7 @@ requires-python = ">=3.10"
|
|||
|
||||
dependencies = [
|
||||
# CLI dependencies
|
||||
"arcade-core>=2.2.1,<3.0.0",
|
||||
"arcade-core>=2.2.2,<3.0.0",
|
||||
"typer==0.10.0",
|
||||
"rich==13.9.4",
|
||||
"Jinja2==3.1.6",
|
||||
|
|
|
|||
Loading…
Reference in a new issue