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

Version 11.1.X maintenance #2404

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/compatibility-tests.yml
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python: ["3.9", "3.10", "3.11", "3.12"]
python: ["3.10", "3.11", "3.12", "3.13"]

services:
postgres:
18 changes: 9 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ jobs:
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.10"
cache: "poetry"

- name: Set UID
@@ -108,7 +108,7 @@ jobs:
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.10"
cache: "poetry"

- name: Set UID
@@ -125,13 +125,6 @@ jobs:
- name: Run tests
run: poetry run pytest --no-cov-on-fail --cov --create-db -vv

compatibility-tests-postgres-12:
name: "Compatibility tests"
uses: ./.github/workflows/compatibility-tests.yml
needs: [lint]
with:
postgres: "12"

compatibility-tests-postgres-13:
name: "Compatibility tests"
uses: ./.github/workflows/compatibility-tests.yml
@@ -159,3 +152,10 @@ jobs:
needs: [lint]
with:
postgres: "16"

compatibility-tests-postgres-17:
name: "Compatibility tests"
uses: ./.github/workflows/compatibility-tests.yml
needs: [lint]
with:
postgres: "17"
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# v11.1.2 (07 March 2025)

### Fix

* **perf:** Don't load full document in memory if not needed for options ([`581d2d0`](https://github.com/projectcaluma/caluma/commit/581d2d056daeee0394c94f20dd64c36ff12a7be8))


# v11.1.1 (04 March 2025)

### Fix
@@ -48,7 +55,10 @@

* Code that uses the form jexl and / or structure code most likely will need to be rewritten. The changes are small-ish, but still semantically not exactly equal. ([`7c997b7`](https://github.com/projectcaluma/caluma/commit/7c997b70850a4c4e7f046714d8a1ab56a89ef950))
See https://github.com/projectcaluma/caluma/pull/2356 for further details.

* While not yet (technically) breaking, we do not support Python versions
of 3.9 and earlier. Update your Python to 3.10 or ideally, 3.13. Support
for Python versions will be according to Python's own version schedule:
https://devguide.python.org/versions/

# v10.7.0 (09 January 2025)

4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ ENV HOME=/home/caluma

ENV PYTHONUNBUFFERED=1
ENV APP_HOME=/app
ENV DJANGO_SETTINGS_MODULE caluma.settings.django
ENV DJANGO_SETTINGS_MODULE=caluma.settings.django

RUN mkdir -p $APP_HOME \
&& useradd -u 901 -r caluma --create-home \
@@ -33,4 +33,4 @@ COPY . $APP_HOME

EXPOSE 8000

CMD /bin/sh -c "wait-for-it $DATABASE_HOST:${DATABASE_PORT:-5432} -- poetry run python manage.py migrate && poetry run gunicorn --workers 10 --access-logfile - --limit-request-line 16384 --bind :8000 caluma.wsgi"
CMD ["/bin/sh", "-c", "wait-for-it $DATABASE_HOST:${DATABASE_PORT:-5432} -- poetry run python manage.py migrate && poetry run gunicorn --workers 10 --access-logfile - --limit-request-line 16384 --bind :8000 caluma.wsgi"]
2 changes: 1 addition & 1 deletion caluma/caluma_form/structure.py
Original file line number Diff line number Diff line change
@@ -332,7 +332,7 @@ def form_by_id(self, form_id: str) -> Form:
return self._forms[form_id]

def rows_for_table_answer(self, answer_id: str) -> list[Document]:
document_ids = self._table_rows_by_answer[str(str(answer_id))]
document_ids = self._table_rows_by_answer[str(answer_id)]
return [self._documents[doc_id] for doc_id in document_ids]

def options_for_question(self, question_id):
40 changes: 40 additions & 0 deletions caluma/caluma_form/tests/test_validators.py
Original file line number Diff line number Diff line change
@@ -799,3 +799,43 @@ def test_validate_integer_0(
with pytest.raises(ValidationError) as excinfo:
DocumentValidator().validate(document, admin_user)
assert excinfo.match("Invalid value 0")


@pytest.mark.parametrize(
"option_jexl, expect_queries, expect_jexl_evaluations",
[
# pre-recognized "visible" jexl, no JEXL and few queries
("", 9, 0),
# pre-recognized "visible" jexl, no JEXL and few queries
("false", 9, 0),
# not pre-recognized - needs to be evaluated in full doc context
# therefore more queries needed, and JEXL expressions are evaluated
("!true", 18, 5),
],
)
def test_validate_options_without_jexl(
db,
django_assert_num_queries,
form_question_factory,
question_option_factory,
document,
option_jexl,
expect_queries,
expect_jexl_evaluations,
mocker,
):
"""Ensure that validating options only evaluates JEXL if actually needed."""
form_question_factory(form=document.form)
form_question_factory(form=document.form)
form_question_factory(form=document.form)
fq = form_question_factory(question__type=Question.TYPE_CHOICE, form=document.form)
options = question_option_factory.create_batch(
5, question=fq.question, option__is_hidden=option_jexl
)

spy = mocker.spy(structure.BaseField, "evaluate_jexl")

with django_assert_num_queries(expect_queries):
api.save_answer(fq.question, document, value=options[3].option_id)

assert spy.call_count == expect_jexl_evaluations
8 changes: 8 additions & 0 deletions caluma/caluma_form/validators.py
Original file line number Diff line number Diff line change
@@ -130,6 +130,14 @@ def _evaluate_options_jexl(
# and use the structure code)
return [o.slug for o in question.options.all()]

elif not validation_context:
# First see if we really need to build up the validation context. If
# not, we can speed things up significantly
all_options = list(question.options.all())
if all(opt.is_hidden in ("false", "") for opt in all_options):
# no JEXL evaluation neccessary
return [o.slug for o in all_options]

field, _root = self._structure_field(document, question, validation_context)
if not field: # pragma: no cover
# This only happens if *programmer* made an error, therefore we're
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "caluma"
version = "11.1.1"
version = "11.1.2"
description = "Caluma Service providing GraphQL API"
homepage = "https://caluma.io"
repository = "https://github.com/projectcaluma/caluma"
Loading