Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: allow AskFileMessage even if spontaneous uploads are disabled #1668

Merged
merged 6 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/lint-backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ jobs:
- name: Lint with ruff
uses: astral-sh/ruff-action@v1
with:
version: '0.8.0'
version: '0.9.0'
src: ${{ env.BACKEND_DIR }}
changed-files: "true"
- name: Check formatting with ruff
uses: astral-sh/ruff-action@v1
with:
version: '0.9.0'
src: ${{ env.BACKEND_DIR }}
changed-files: "true"
args: "format --check"
Expand Down
15 changes: 7 additions & 8 deletions backend/chainlit/auth/cookie.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
os.environ.get("CHAINLIT_COOKIE_SAMESITE", "lax"),
)

assert (
_cookie_samesite
in [
"lax",
"strict",
"none",
]
), "Invalid value for CHAINLIT_COOKIE_SAMESITE. Must be one of 'lax', 'strict' or 'none'."
assert _cookie_samesite in [
"lax",
"strict",
"none",
], (
"Invalid value for CHAINLIT_COOKIE_SAMESITE. Must be one of 'lax', 'strict' or 'none'."
)
_cookie_secure = _cookie_samesite == "none"

_auth_cookie_lifetime = 60 * 60 # 1 hour
Expand Down
2 changes: 1 addition & 1 deletion backend/chainlit/data/chainlit_data_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ async def update_thread(

# Build the query dynamically based on available fields
columns = [f'"{k}"' for k in data.keys()]
placeholders = [f"${i+1}" for i in range(len(data))]
placeholders = [f"${i + 1}" for i in range(len(data))]
values = list(data.values())

update_sets = [f'"{k}" = EXCLUDED."{k}"' for k in data.keys() if k != "id"]
Expand Down
2 changes: 1 addition & 1 deletion backend/chainlit/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ async def send(self) -> Union[AskActionResponse, None]:
if res is None:
self.content = "Timed out: no action was taken"
else:
self.content = f'**Selected:** {res["label"]}'
self.content = f"**Selected:** {res['label']}"

self.wait_for_answer = False

Expand Down
33 changes: 22 additions & 11 deletions backend/chainlit/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1123,11 +1123,14 @@ def validate_file_upload(file: UploadFile):
Raises:
ValueError: If the file is not allowed.
"""
if config.features.spontaneous_file_upload is None:
"""Default for a missing config is to allow the fileupload without any restrictions"""
return
if config.features.spontaneous_file_upload.enabled is False:
raise ValueError("File upload is not enabled")
# TODO: This logic/endpoint is shared across spontaneous uploads and the AskFileMessage API.
# Commenting this check until we find a better solution

# if config.features.spontaneous_file_upload is None:
# """Default for a missing config is to allow the fileupload without any restrictions"""
# return
# if not config.features.spontaneous_file_upload.enabled:
# raise ValueError("File upload is not enabled")

validate_file_mime_type(file)
validate_file_size(file)
Expand All @@ -1140,14 +1143,19 @@ def validate_file_mime_type(file: UploadFile):
Raises:
ValueError: If the file type is not allowed.
"""
accept = config.features.spontaneous_file_upload.accept
if accept is None:

if (
config.features.spontaneous_file_upload is None
or config.features.spontaneous_file_upload.accept is None
):
"Accept is not configured, allowing all file types"
return

assert (
isinstance(accept, List) or isinstance(accept, dict)
), "Invalid configuration for spontaneous_file_upload, accept must be a list or a dict"
accept = config.features.spontaneous_file_upload.accept

assert isinstance(accept, List) or isinstance(accept, dict), (
"Invalid configuration for spontaneous_file_upload, accept must be a list or a dict"
)

if isinstance(accept, List):
for pattern in accept:
Expand All @@ -1171,7 +1179,10 @@ def validate_file_size(file: UploadFile):
Raises:
ValueError: If the file size is too large.
"""
if config.features.spontaneous_file_upload.max_size_mb is None:
if (
config.features.spontaneous_file_upload is None
or config.features.spontaneous_file_upload.max_size_mb is None
):
return

if (
Expand Down
573 changes: 290 additions & 283 deletions backend/poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ script = "build.py"
[tool.poetry.dependencies]
python = ">=3.9,<4.0.0"
httpx = ">=0.23.0"
literalai = "0.0.623"
literalai = "0.1.103"
dataclasses_json = "^0.6.7"
fastapi = ">=0.115.3,<0.116"
starlette = "^0.41.2"
Expand Down Expand Up @@ -86,7 +86,7 @@ pandas = "^2.2.2"
moto = "^5.0.14"

[tool.poetry.group.dev.dependencies]
ruff = "^0.8.0"
ruff = "^0.9.0"

[tool.poetry.group.mypy]
optional = true
Expand Down
60 changes: 30 additions & 30 deletions backend/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,36 +500,36 @@ def test_upload_file_unauthorized(
assert response.status_code == 422


def test_upload_file_disabled(
test_client: TestClient,
test_config: ChainlitConfig,
mock_session_get_by_id_patched: Mock,
monkeypatch: pytest.MonkeyPatch,
):
"""Test file upload being disabled by config."""

# Set accept in config
monkeypatch.setattr(
test_config.features,
"spontaneous_file_upload",
SpontaneousFileUploadFeature(enabled=False),
)

# Prepare the files to upload
file_content = b"Sample file content"
files = {
"file": ("test_upload.txt", file_content, "text/plain"),
}

# Make the POST request to upload the file
response = test_client.post(
"/project/file",
files=files,
params={"session_id": mock_session_get_by_id_patched.id},
)

# Verify the response
assert response.status_code == 400
# def test_upload_file_disabled(
# test_client: TestClient,
# test_config: ChainlitConfig,
# mock_session_get_by_id_patched: Mock,
# monkeypatch: pytest.MonkeyPatch,
# ):
# """Test file upload being disabled by config."""

# # Set accept in config
# monkeypatch.setattr(
# test_config.features,
# "spontaneous_file_upload",
# SpontaneousFileUploadFeature(enabled=False),
# )

# # Prepare the files to upload
# file_content = b"Sample file content"
# files = {
# "file": ("test_upload.txt", file_content, "text/plain"),
# }

# # Make the POST request to upload the file
# response = test_client.post(
# "/project/file",
# files=files,
# params={"session_id": mock_session_get_by_id_patched.id},
# )

# # Verify the response
# assert response.status_code == 400


@pytest.mark.parametrize(
Expand Down
Loading