Skip to content

Commit 105820b

Browse files
Merge pull request #1770 from gooddata/snapshot-master-12861e2b-to-rel/dev
[bot] Merge master/12861e2b into rel/dev
2 parents 8607fcb + 12861e2 commit 105820b

19 files changed

Lines changed: 113 additions & 114 deletions

File tree

.github/workflows/rw-python-tests.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ jobs:
4444
- name: pep8 and formatting check
4545
run: |
4646
make format
47+
- name: lint check
48+
run: |
49+
make lint
4750
docs-scripts-tests:
4851
runs-on: ubuntu-latest
4952
if: ${{inputs.changed-python-modules == 'true'}}

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ repos:
1515
args: [ '--maxkb=890' ]
1616
- id: check-case-conflict
1717
- repo: https://github.com/astral-sh/ruff-pre-commit
18-
rev: v0.15.1
18+
rev: v0.15.20
1919
hooks:
2020
# Run the linter.
2121
- id: ruff

Dockerfile

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# (C) 2021 GoodData Corporation
22
ARG PY_TAG
3-
FROM ghcr.io/astral-sh/uv:0.12 AS uv
3+
FROM ghcr.io/astral-sh/uv:0.12.5 AS uv
44
FROM python:${PY_TAG}
55

66
ARG PY_TAG
@@ -40,16 +40,35 @@ WORKDIR /data
4040
COPY pyproject.toml uv.lock ./
4141

4242
# Install tox and tox-uv as system packages so they're available globally.
43-
# NOTE: `uv pip install --group` reads the group's requirements from pyproject.toml but
44-
# resolves them FRESH from the index -- it does NOT read uv.lock. Every version that must
45-
# stay fixed therefore needs an explicit bound in the group itself; in particular `uv`,
46-
# whose console script installs over the binary copied above.
43+
# Via `uv export` and not `uv pip install --group`: the latter re-resolves fresh from the
44+
# index, while export reads uv.lock, so the image gets exactly the pinned versions.
45+
# The group uses tox-uv-bare, so nothing here installs a `uv` console script over the
46+
# binary COPYed above -- that COPY is the image's only uv, hence its exact pin.
4747
# Clean up dependency files after installation to reduce image size
4848
RUN set -x \
49-
&& uv pip install --system --group tox \
50-
&& rm -f pyproject.toml uv.lock \
49+
&& uv export --frozen --only-group tox -o /tmp/tox-requirements.txt \
50+
&& uv pip install --system -r /tmp/tox-requirements.txt \
51+
&& rm -f pyproject.toml uv.lock /tmp/tox-requirements.txt \
5152
&& true
5253

54+
# Any uv command here must not REWRITE the bind-mounted host uv.lock if it thinks it is
55+
# stale -- fail instead. Not UV_FROZEN: tox-uv reads that and downgrades its own --locked
56+
# to --frozen, silently accepting a stale lock. Must be set AFTER the export above, which
57+
# is rejected in combination with UV_LOCKED and has to stay --frozen because only the root
58+
# pyproject.toml and uv.lock exist at that layer for --locked to validate against.
59+
ENV UV_LOCKED=1
60+
61+
# Use the lock-pinned tox installed system-wide above rather than project_common.mk's
62+
# default `uv run tox`, which would first sync the whole workspace into a throwaway
63+
# in-container project env (measured: 58 packages, ~7s) just to obtain the same tox.
64+
ENV TOX=tox
65+
66+
# The repo is bind-mounted at /data, so the default project environment (/data/.venv) is
67+
# the developer's host venv; a `uv run` here would rebuild it against this image's Linux
68+
# interpreter. Redirect it somewhere container-local (/tmp, not a home dir: the runtime
69+
# user is created by entrypoint.sh, so no home exists when this ENV is evaluated).
70+
ENV UV_PROJECT_ENVIRONMENT=/tmp/uv-project-venv
71+
5372
COPY .docker/entrypoint.sh /entrypoint.sh
5473

5574
LABEL image_name="GoodData Python SDK test image with python, tox and make"

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ test-staging:
104104
clean-staging:
105105
@test -n "$(STAGING_ADMIN_TOKEN)" || (echo "ERROR: STAGING_ADMIN_TOKEN is required. Set it in .env or pass on CLI." && exit 1)
106106
@test -n "$(STAGING_DS_PASSWORD)" || (echo "ERROR: STAGING_DS_PASSWORD is required. Set it in .env or pass on CLI." && exit 1)
107-
cd packages/tests-support && STAGING=1 TOKEN="$(STAGING_ADMIN_TOKEN)" DS_PASSWORD="$(STAGING_DS_PASSWORD)" python clean_staging.py
107+
cd packages/tests-support && STAGING=1 TOKEN="$(STAGING_ADMIN_TOKEN)" DS_PASSWORD="$(STAGING_DS_PASSWORD)" uv run --locked python clean_staging.py
108108

109109
.PHONY: load-staging
110110
load-staging:
111111
@test -n "$(STAGING_ADMIN_TOKEN)" || (echo "ERROR: STAGING_ADMIN_TOKEN is required. Set it in .env or pass on CLI." && exit 1)
112112
@test -n "$(STAGING_DS_PASSWORD)" || (echo "ERROR: STAGING_DS_PASSWORD is required. Set it in .env or pass on CLI." && exit 1)
113-
cd packages/tests-support && STAGING=1 TOKEN="$(STAGING_ADMIN_TOKEN)" DS_PASSWORD="$(STAGING_DS_PASSWORD)" python upload_demo_layout.py
113+
cd packages/tests-support && STAGING=1 TOKEN="$(STAGING_ADMIN_TOKEN)" DS_PASSWORD="$(STAGING_DS_PASSWORD)" uv run --locked python upload_demo_layout.py
114114

115115
.PHONY: release
116116
release:

packages/gooddata-dbt/tox.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ envlist = py3{10,11,12,13,14}
55
[testenv]
66
runner = uv-venv-lock-runner
77
package = wheel
8-
wheel_build_env = .pkg
98
dependency_groups =
109
test
1110
setenv =

packages/gooddata-eval/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# (C) 2026 GoodData Corporation
2+
3+
# Unit test / coverage reports
4+
.tox/
5+
.coverage
6+
.coverage.*
7+
coverage.xml
8+
.json-report-*.json

packages/gooddata-eval/src/gooddata_eval/core/chat/sse_client.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,11 @@ def _is_retryable_exc(exc: Exception) -> bool:
8989
return True
9090
if isinstance(exc, httpx.HTTPStatusError):
9191
return exc.response.status_code in _RETRYABLE_STATUS_CODES
92-
if isinstance(exc, httpx.RemoteProtocolError):
93-
# Mid-stream disconnect ("peer closed connection without sending complete
94-
# message body") -- pure network flake, not a real agent/content failure.
95-
# Confirmed live: contaminated ~1-4% of visualization runs with a hard
96-
# fail and zero retry attempts.
97-
return True
98-
return False
92+
# Mid-stream disconnect ("peer closed connection without sending complete
93+
# message body") -- pure network flake, not a real agent/content failure.
94+
# Confirmed live: contaminated ~1-4% of visualization runs with a hard
95+
# fail and zero retry attempts.
96+
return isinstance(exc, httpx.RemoteProtocolError)
9997

10098

10199
def _retry_transient(operation: Callable[[], T], *, is_retryable: Callable[[Exception], bool]) -> T:

packages/gooddata-eval/tests/test_agentic_runner.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from unittest.mock import patch
44

55
import pytest
6-
from gooddata_eval.cli.agentic_runner import _dispatch_agentic, run_agentic_items
6+
from gooddata_eval.cli.agentic_runner import AGENTIC_TEST_KINDS, _dispatch_agentic, run_agentic_items
77
from gooddata_eval.core.agentic.alert_skill import AlertSkillAssertionError
88
from gooddata_eval.core.models import AgenticEvalOutcome, DatasetItem
99

@@ -81,8 +81,6 @@ def test_all_agentic_kind_cases_covers_every_registered_kind():
8181
"""Guards the two parametrized tests below against silently going stale: a kind added
8282
to AGENTIC_TEST_KINDS without a matching case here would otherwise just not get tested,
8383
not fail loudly."""
84-
from gooddata_eval.cli.agentic_runner import AGENTIC_TEST_KINDS
85-
8684
covered = {kind for kind, _, _ in _ALL_AGENTIC_KIND_CASES}
8785
assert covered == set(AGENTIC_TEST_KINDS)
8886

@@ -194,8 +192,6 @@ def test_dispatch_agentic_returns_a_real_outcome_for_every_kind(kind, expected_o
194192
evaluator produced -- not None, not the outcome's reasoning_steps list alone, not any
195193
other bare value the old `isinstance(outcome, tuple)`/`isinstance(outcome, AgenticEvalOutcome)`
196194
fallback could silently swallow."""
197-
from gooddata_eval.core.models import AgenticEvalOutcome
198-
199195
item = DatasetItem(
200196
id="q1",
201197
dataset_name="ds",

packages/gooddata-eval/tox.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ envlist = py3{10,11,12,13,14}
55
[testenv]
66
runner = uv-venv-lock-runner
77
package = wheel
8-
wheel_build_env = .pkg
98
extras =
109
llm-judge
1110
dependency_groups =

packages/gooddata-fdw/tox.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ envlist = py3{10,11,12,13,14}
55
[testenv]
66
runner = uv-venv-lock-runner
77
package = wheel
8-
wheel_build_env = .pkg
98
dependency_groups =
109
test
1110
setenv =

0 commit comments

Comments
 (0)