Skip to content

Addition of Saving and Loading of Filter Presets [WIP]#4755

Open
feyruzb wants to merge 21 commits intoEricsson:masterfrom
feyruzb:feat/filter-preset-feature
Open

Addition of Saving and Loading of Filter Presets [WIP]#4755
feyruzb wants to merge 21 commits intoEricsson:masterfrom
feyruzb:feat/filter-preset-feature

Conversation

@feyruzb
Copy link
Collaborator

@feyruzb feyruzb commented Jan 15, 2026

This pull request introduces a new "filter preset" feature to CodeChecker, allowing users to create, manage, and apply named collections of filter configurations for analysis results. It includes updates to the Thrift API, CLI commands, and versioning to support this functionality. The most important changes are outlined below.

Filter Preset Feature Implementation

  • Added a new FilterPreset struct and related API endpoints (storeFilterPreset, getFilterPreset, deleteFilterPreset, listFilterPreset) to report_server.thrift for managing filter presets on the server. [1] [2]
  • Added new menu and buttons for applying the Presets in Products.
image image
  • Updated the CLI (cmd.py) to support new filter-preset subcommands (list, new, delete) for managing filter presets, and added a --filter-preset argument to allow users to apply a preset when running commands. [1] [2] [3]
  • list option can be used in 2 modes, first is json flag that displays full detailed information the rest like csv , plaintext and table uses summarization function that only displays existing filters in object.
  • Implemented logic in the CLI to load and merge filter presets from the server with command-line arguments, giving precedence to CLI arguments. [1] [2]
  • Added client helper methods for new filter preset API calls in results.py.

Versioning and Compatibility Updates

  • Bumped API and package versions to 6.68.0 in package.json, setup.py, and version.py to reflect the new feature and maintain compatibility.

Developer Tooling

  • Added a new script completly-rebuild-thrift.sh to automate rebuilding the Thrift API and related environments for developers.

Other API Enhancements

  • Added a getNameByValueForFilter endpoint to the Thrift API for resolving names based on values and class names. !THIS FUNCTION IS GOING TO BE DELETED, IT IS IN PR UNTIL DECIDED OTHERWISE!

@feyruzb feyruzb self-assigned this Jan 16, 2026
@feyruzb feyruzb added enhancement 🌟 API change 📄 Content of patch changes API! WIP 💣 Work In Progress GUI 🎨 server 🖥️ web 🌍 Related to the web app new feature 👍 New feature request javascript Pull requests that update JavaScript code (used by DependaBot) python Pull requests that update Python code (used by DependaBot) labels Jan 16, 2026
Copy link
Collaborator

@gulyasgergely902 gulyasgergely902 left a comment

Choose a reason for hiding this comment

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

Overall good work, I've found only minor issues (even nitpicks) which can be fixed in no time. Please check the TODOs and comments with question marks and make them clear for the future. What I'm missing are the tests for the new functions. Please check them and write tests in the corresponding unit test folders.

export PATH="$HOME/codechecker/build/CodeChecker/bin:$PATH"

echo "CodeChecker rebuild completed successfully!"
echo "You can now use CodeChecker commands." No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add a new line to the end of the file, git can complain about missing new lines at the end of any text files.

Copy link
Collaborator Author

@feyruzb feyruzb Feb 19, 2026

Choose a reason for hiding this comment

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

Fixed.

// if the id is -1 a new preset filter is created
// the filter preset name must be unique.
// An error must be thrown if another preset exists with the same name.
// The encoding of the name must be unicode. (whitespaces allowed?)
Copy link
Collaborator

Choose a reason for hiding this comment

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

In this line, "whitespaces allowed?" suggests me that this part is not yet complete. Please decide if either allowed or not and edit the comment accordingly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

// Filter grouping api calls.
//============================================

// Stores the given FilterPreset with the given id
Copy link
Collaborator

Choose a reason for hiding this comment

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

I got a few questions / remarks regarding this part:

  • Does it check the id of the incoming FilterPreset to decide if it exists or not? If so, please modify the first line accordingly (e.g. "If the a preset exists with the given id, it overwrites the name, and all preset values.")
  • Fix the second line to match the first: "If the preset does not exist yet, it creates it with the given id.".
  • The line "if the id is -1 a new preset filter is created" is confusing so if I add -1 as an id, it forcibly creates the filter? And if so, what will be the actual id after creation?
  • Please make all new sentences start with a capital letter and finish with a dot.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

FilterPreset getFilterPreset(1: i64 id)
throws (1: codechecker_api_shared.RequestFailed requestError);

// Removes the filterpreset with the given id
Copy link
Collaborator

Choose a reason for hiding this comment

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

It should be written as "FilterPreset" to be uniform to the other comments.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

description=description))
return results

# Stores the given FilterPreset with the given id
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest you do the same modifications I've suggested above for the same comment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

if preset is None:
return None

# convert ORM to dict for ReportFilter
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# convert ORM to dict for ReportFilter
# Convert ORM to dict for ReportFilter

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

if not token:
return ""

# special case for formatting confirmed bug. IN UI for some reason
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# special case for formatting confirmed bug. IN UI for some reason
# Special case for formatting confirmed bug. IN UI for some reason

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

session.add(preset_entry)
session.commit()
return int(preset_entry.id)
return -1
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not a terrible thing but some linters may complain about using magic numbers. You could create a const for it either here or in a global file (there might be already a file for status and error codes in codechecker) which you could use as a return value. E.g. FILTER_PRESET_ERROR = -1 or similar.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

Delete preset from products list based on preset_id.
"""
self.__require_admin()
LOG.info("deleting filter preset by id")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
LOG.info("deleting filter preset by id")
LOG.info("Deleting filter preset by ID")

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

Returns the FilterPreset identified by id.
"""
self.__require_view()
LOG.info("Returning filter Preset by id")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
LOG.info("Returning filter Preset by id")
LOG.info("Returning filter Preset by ID")

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

@gulyasgergely902
Copy link
Collaborator

One more thing which I've missed: Besides the unit tests, please also write functional tests, for the API too.

@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch 14 times, most recently from 3383a3f to a738d47 Compare February 18, 2026 16:04
@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch 3 times, most recently from 481c8ad to 60a96ba Compare February 19, 2026 09:29

// Return name based on mapping based on value and classname.
// PERMISSION: PRODUCT_VIEW
string getNameByValueForFilter(1: string classname,
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this function used? If not needed, then it should be removed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed.

help="Get report details for reports such as bug path "
"events, bug report points etc.")

parser.add_argument('--filterPreset',
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's follow the naming conventions: --filter-preset.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

"is loaded from the server and applied to the "
"results. You can override specific filters by "
"providing additional filter arguments. Use "
"'CodeChecker cmd filterPreset list' to see "
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's rename it filter-preset.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

action='store_true',
dest='force',
required=False,
help="Force deletion without confirmation.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Resetting is forced here instead of deletion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed, --force is deleted.

__add_common_arguments(tasks, needs_product_url=False)

filter_preset = subcommands.add_parser(
'filter_preset',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
'filter_preset',
'filter-preset',

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

LOG.info("Filter preset was not deleted.")
sys.exit(0)

success = client.deleteFilterPreset(args.preset_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

The function returns -1 in case of failure. That should be checked in the next statement. It would be even better if the function would throw an exception instead of returning -1 because that could explain the reason of error better.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.


// Removes the filterpreset with the given id
// returns the id of the filter preset removed
// and -1 in case of error.
Copy link
Contributor

Choose a reason for hiding this comment

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

The function should throw an error in case of error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

)

if preset is None:
return -1
Copy link
Contributor

Choose a reason for hiding this comment

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

An error should be thrown. The return value of this function is FilterPreset according to the .thrift file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.


# Convert ORM to dict for ReportFilter
rf = preset.report_filter
if isinstance(rf, str):
Copy link
Contributor

Choose a reason for hiding this comment

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

How can this field be a different type? If it's possibly None, then that should be checked. I have the same question for the next fields, too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed.

if not all_presets:
return []

list_of_all_presets = [self.getFilterPreset(preset.id) for preset in all_presets]
Copy link
Contributor

Choose a reason for hiding this comment

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

The content of getFilterPreset() could go to a helper function that assembles a ReportFilter object based on a PresetFilter. This way it wouldn't be needed to do as many database queries as many presets we have.

Copy link
Contributor

@bruntib bruntib Feb 23, 2026

Choose a reason for hiding this comment

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

def transform(dbFilterPreset)
    return thriftfilterpreset


getFilterPreset(id)
    x = dbQuery(id)
    transform(x)
    
listFilterPreset()
    all = dbQuery
    for blabla in all:
        transform(blabla)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch from 9aa6c06 to 3491e07 Compare February 25, 2026 17:42
@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch from 3491e07 to afc62e0 Compare February 26, 2026 10:38
@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch from 847d099 to 68e1cd3 Compare February 27, 2026 14:16
@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch from 68e1cd3 to 0132c0c Compare February 27, 2026 14:41
@feyruzb feyruzb force-pushed the feat/filter-preset-feature branch from fa220f6 to 003fad6 Compare March 2, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API change 📄 Content of patch changes API! enhancement 🌟 GUI 🎨 javascript Pull requests that update JavaScript code (used by DependaBot) new feature 👍 New feature request python Pull requests that update Python code (used by DependaBot) server 🖥️ web 🌍 Related to the web app WIP 💣 Work In Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants