Fix venv files not being found (#525)

This commit is contained in:
Sterling Dreyer 2025-08-01 12:12:35 -07:00 committed by GitHub
parent 21f892c0a0
commit 7888dc505e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 34 additions and 91 deletions

View file

@ -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

View file

@ -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

View file

@ -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"}

View file

@ -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

View file

@ -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",