Skip to content

Fix QbField issues - #7463

Merged
edan-bainglass merged 17 commits into
aiidateam:mainfrom
edan-bainglass:fix-qbfields
Aug 5, 2026
Merged

Fix QbField issues#7463
edan-bainglass merged 17 commits into
aiidateam:mainfrom
edan-bainglass:fix-qbfields

Conversation

@edan-bainglass

@edan-bainglass edan-bainglass commented Jul 19, 2026

Copy link
Copy Markdown
Member

This PR fixes the following incorrect QbAnyField assignments:

type correct QB field class
bool QbBoolField
UUID QbStrField
Sequence QbArrayField

Regarding the new QbBoolField, this now allows for the following:

  • filters=CalcJobNode.fields.paused
  • filters=... & CalcJobNode.fields.paused (or |)
  • filters=CalcJobNode.fields.paused & ... (or |)
  • filters=~CalcJobNode.fields.paused (implemented as "not True" instead of "is False" - see reason)

In other words, boolean-based queries are now supported!

For Enum field annotations, I keep it as QbAnyField, as the value can be anything (we have int, str, and tuple[str] in core). Also, I was thinking of falling back to QbField if the annotation is not matched but decided in the end to keep it all-permissive, i.e., QbAnyField.

Lastly, this PR also addresses the issue that attributes['value'] doesn't return the same QbField as attributes.value when value is a defined attribute on the node model. When the key is not a defined attribute, we defer to the QbDictField indexing behavior of returning a QbAnyField.

This addresses a part of #7461 but does not yet close it.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The query field system adds typed boolean filters and sequence-based array dispatch. Numeric metadata is modeled explicitly, QueryBuilder accepts boolean fields, ORM tests cover boolean filtering, and field schemas use more specific boolean, UUID, numeric, and array declarations.

Changes

Typed query fields and ORM schemas

Layer / File(s) Summary
Boolean field behavior and dtype dispatch
src/aiida/orm/fields.py
Adds QbBoolField, boolean filter operators, boolean filter combination, and Sequence-aware field dispatch.
Numeric metadata and query processing
src/aiida/orm/nodes/data/numeric.py, src/aiida/orm/querybuilder.py
Adds typed numeric attributes and converts QbBoolField inputs before filter validation.
Data and code field declarations
tests/orm/test_fields/fields_*.yml, tests/orm/test_fields/fields_aiida.data.core.*/**
Replaces generic declarations with typed boolean, UUID string, numeric, and array fields.
Process field declarations
tests/orm/test_fields/fields_aiida.node.process.*/**
Uses typed boolean and UUID fields for process attributes and array fields for retrieval lists.
Boolean query validation
tests/orm/test_fields.py
Tests boolean equality, negation, combined boolean filters, and label filtering.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Suggested reviewers: geigerj2

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately identifies the main change as fixing QbField issues, although it does not specify the boolean, UUID, or sequence updates.
Description check ✅ Passed The description clearly explains the corrected field mappings, boolean query support, and related scope of the changes.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@edan-bainglass
edan-bainglass requested a review from GeigerJ2 July 19, 2026 08:47
@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.14286% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.67%. Comparing base (dc0ba9c) to head (10daf08).

Files with missing lines Patch % Lines
src/aiida/orm/fields.py 96.56% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7463      +/-   ##
==========================================
+ Coverage   80.65%   80.67%   +0.02%     
==========================================
  Files         581      581              
  Lines       46987    47014      +27     
==========================================
+ Hits        37893    37923      +30     
+ Misses       9094     9091       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/aiida/orm/fields.py (1)

159-173: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add type annotations to QbBoolField methods.

As per coding guidelines, types should be written in annotations. Adding type hints to these methods improves developer ergonomics and aligns with the rest of the file (e.g., QbFieldFilters).

♻️ Proposed refactor
-    def as_filter(self):
+    def as_filter(self) -> QbFieldFilters:
         """Return a filter for only values that are True."""
         return QbFieldFilters(((self, '==', True),))

-    def __and__(self, other):
+    def __and__(self, other: QbFieldFilters | QbBoolField) -> QbFieldFilters:
         """Return a filter for only values that are True and satisfy the other filter."""
         return self.as_filter() & other

-    def __or__(self, other):
+    def __or__(self, other: QbFieldFilters | QbBoolField) -> QbFieldFilters:
         """Return a filter for only values that are True or satisfy the other filter."""
         return self.as_filter() | other

-    def __invert__(self):
+    def __invert__(self) -> QbFieldFilters:
         """Return a filter for only values that are False."""
         return QbFieldFilters(((self, '==', False),))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aiida/orm/fields.py` around lines 159 - 173, Update the QbBoolField
methods as_filter, __and__, __or__, and __invert__ with appropriate parameter
and return type annotations, including the other argument for the binary
operators. Match the existing annotation conventions used by QbFieldFilters and
preserve the current filter behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/aiida/orm/fields.py`:
- Around line 159-173: Update the QbBoolField methods as_filter, __and__,
__or__, and __invert__ with appropriate parameter and return type annotations,
including the other argument for the binary operators. Match the existing
annotation conventions used by QbFieldFilters and preserve the current filter
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 256b4f66-5d5a-426e-a4dc-3bc71c514f31

📥 Commits

Reviewing files that changed from the base of the PR and between 56ace5b and 1c48325.

📒 Files selected for processing (48)
  • src/aiida/orm/fields.py
  • src/aiida/orm/nodes/data/numeric.py
  • src/aiida/orm/querybuilder.py
  • tests/orm/test_fields/fields_AuthInfo.yml
  • tests/orm/test_fields/fields_Comment.yml
  • tests/orm/test_fields/fields_Computer.yml
  • tests/orm/test_fields/fields_Group.yml
  • tests/orm/test_fields/fields_Log.yml
  • tests/orm/test_fields/fields_aiida.data.core.array.ArrayData.yml
  • tests/orm/test_fields/fields_aiida.data.core.array.bands.BandsData.yml
  • tests/orm/test_fields/fields_aiida.data.core.array.kpoints.KpointsData.yml
  • tests/orm/test_fields/fields_aiida.data.core.array.projection.ProjectionData.yml
  • tests/orm/test_fields/fields_aiida.data.core.array.trajectory.TrajectoryData.yml
  • tests/orm/test_fields/fields_aiida.data.core.array.xy.XyData.yml
  • tests/orm/test_fields/fields_aiida.data.core.base.BaseType.yml
  • tests/orm/test_fields/fields_aiida.data.core.bool.Bool.yml
  • tests/orm/test_fields/fields_aiida.data.core.cif.CifData.yml
  • tests/orm/test_fields/fields_aiida.data.core.code.Code.yml
  • tests/orm/test_fields/fields_aiida.data.core.code.abstract.AbstractCode.yml
  • tests/orm/test_fields/fields_aiida.data.core.code.containerized.ContainerizedCode.yml
  • tests/orm/test_fields/fields_aiida.data.core.code.installed.InstalledCode.yml
  • tests/orm/test_fields/fields_aiida.data.core.code.portable.PortableCode.yml
  • tests/orm/test_fields/fields_aiida.data.core.dict.Dict.yml
  • tests/orm/test_fields/fields_aiida.data.core.enum.EnumData.yml
  • tests/orm/test_fields/fields_aiida.data.core.float.Float.yml
  • tests/orm/test_fields/fields_aiida.data.core.folder.FolderData.yml
  • tests/orm/test_fields/fields_aiida.data.core.int.Int.yml
  • tests/orm/test_fields/fields_aiida.data.core.jsonable.JsonableData.yml
  • tests/orm/test_fields/fields_aiida.data.core.list.List.yml
  • tests/orm/test_fields/fields_aiida.data.core.numeric.NumericType.yml
  • tests/orm/test_fields/fields_aiida.data.core.orbital.OrbitalData.yml
  • tests/orm/test_fields/fields_aiida.data.core.remote.RemoteData.yml
  • tests/orm/test_fields/fields_aiida.data.core.remote.stash.RemoteStashData.yml
  • tests/orm/test_fields/fields_aiida.data.core.remote.stash.compress.RemoteStashCompressedData.yml
  • tests/orm/test_fields/fields_aiida.data.core.remote.stash.custom.RemoteStashCustomData.yml
  • tests/orm/test_fields/fields_aiida.data.core.remote.stash.folder.RemoteStashFolderData.yml
  • tests/orm/test_fields/fields_aiida.data.core.singlefile.SinglefileData.yml
  • tests/orm/test_fields/fields_aiida.data.core.str.Str.yml
  • tests/orm/test_fields/fields_aiida.data.core.structure.StructureData.yml
  • tests/orm/test_fields/fields_aiida.data.core.upf.UpfData.yml
  • tests/orm/test_fields/fields_aiida.node.data.Data.yml
  • tests/orm/test_fields/fields_aiida.node.process.ProcessNode.yml
  • tests/orm/test_fields/fields_aiida.node.process.calculation.CalculationNode.yml
  • tests/orm/test_fields/fields_aiida.node.process.calculation.calcfunction.CalcFunctionNode.yml
  • tests/orm/test_fields/fields_aiida.node.process.calculation.calcjob.CalcJobNode.yml
  • tests/orm/test_fields/fields_aiida.node.process.workflow.WorkflowNode.yml
  • tests/orm/test_fields/fields_aiida.node.process.workflow.workchain.WorkChainNode.yml
  • tests/orm/test_fields/fields_aiida.node.process.workflow.workfunction.WorkFunctionNode.yml

@edan-bainglass

edan-bainglass commented Jul 19, 2026

Copy link
Copy Markdown
Member Author

@GeigerJ2 two comments:

  1. The rabbit is not bad. It is quite helpful and will likely save us time in the long run. I'm happy to attest to this in the next meeting!
  2. I've accepted its suggestion w.r.t type annotations in the new QbBoolField class, but in principle, the whole of the fields.py module needs an upgrade w.r.t type annotations. I'll do this in a separate PR.

@edan-bainglass

edan-bainglass commented Jul 19, 2026

Copy link
Copy Markdown
Member Author

Interesting. That test passes locally no problem.

Update

May have been due to running that test in isolation. When running the full suite, assigned PKs may be different. Using labels instead to uniquly identify the tested nodes!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/orm/test_fields.py (1)

252-252: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Prevent potential test flakiness by making the assertion order-independent.

Without an explicit order_by clause in the query, relational databases do not guarantee the order of the returned rows. Comparing the result directly to the list [True, False] could lead to intermittent test failures if the backend returns the rows in a different order (e.g., [False, True]).

Consider using a set to perform an order-independent comparison.

♻️ Proposed fix
-    assert result == [True, False]
+    assert set(result) == {True, False}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/orm/test_fields.py` at line 252, Make the assertion in the affected
test order-independent by comparing the result as a set to the expected boolean
values. Preserve the existing query and expected contents while allowing either
database row order.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/orm/test_fields.py`:
- Line 252: Make the assertion in the affected test order-independent by
comparing the result as a set to the expected boolean values. Preserve the
existing query and expected contents while allowing either database row order.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d4479947-ea86-46d0-8e1c-0b5c9c9fefe5

📥 Commits

Reviewing files that changed from the base of the PR and between ffe0ddb and 89f1b02.

📒 Files selected for processing (2)
  • src/aiida/orm/fields.py
  • tests/orm/test_fields.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/aiida/orm/fields.py

@agoscinski

Copy link
Copy Markdown
Collaborator

Guys this is an API extension, you cannot put it into a patch release.

@agoscinski agoscinski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be at least some small update in the RTD i guess?

title='Numeric value',
description='The value of the numeric data',
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this change only done in this pr and not in the bigger pydantic upgrade?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed

user: QbNumericField('user', dtype=<class 'int'>, doc='The PK of the user who owns
the node')
uuid: QbAnyField('uuid', dtype=<class 'uuid.UUID'>, doc='The UUID of the node')
uuid: QbStrField('uuid', dtype=<class 'uuid.UUID'>, doc='The UUID of the node')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why also the update to str, i thought u only add bool in this PR

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refer to the PR description

@edan-bainglass

edan-bainglass commented Aug 4, 2026

Copy link
Copy Markdown
Member Author

Guys this is an API extension, you cannot put it into a patch release.

@GeigerJ2 👀

Just to be clear, it is an API extension, not a breaking change, correct? If so, I don't see a reason not to add it to the upcoming 2.9 release 🙂

@edan-bainglass

Copy link
Copy Markdown
Member Author

Just to be clear, it is an API extension, not a breaking change, correct? If so, I don't see a reason not to add it to the upcoming 2.9 release 🙂

Fine to leave this off the release if too stressful 🧘🏻‍♂️

@GeigerJ2 GeigerJ2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just had a look at the Python files so far. I expect the YAML changes will be correct and mechanical. One point to address, already posting now, while I glance over the YAML files.

Comment thread src/aiida/orm/fields.py Outdated
Comment thread tests/orm/test_fields.py
@edan-bainglass
edan-bainglass requested a review from GeigerJ2 August 5, 2026 05:45
@edan-bainglass edan-bainglass changed the title Fix a few incorrect QbField type assignments Fix QbField issues Aug 5, 2026

@GeigerJ2 GeigerJ2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks a lot, @edan-bainglass! Just one comment on test_attribute_field_access, but already approving now :)

Comment thread tests/orm/test_fields.py Outdated
@edan-bainglass
edan-bainglass merged commit 9726630 into aiidateam:main Aug 5, 2026
19 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in aiida-core v2.9.0 Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants