feat: allow repeated --filter flags for exports - #443
Conversation
Previously `--filter` accepted only one value, and multi-pair filtering required joining pairs with '&' (e.g. `--filter "A=1&B=2"`). That parsing scheme conflicts with values that legitimately contain '&' (e.g. `Product Name=AT&T ...`). Make `--filter` repeatable via argparse action="append". Each flag now carries exactly one COLUMN=VALUE pair — no '&' splitting — so literal '&' in a value passes through untouched. Back-compat: when only one --filter flag is present, the value is still split on '&' so existing scripts keep working. Users who need '&' in a value should switch to the repeated-flag form. Adds parser tests for the new syntax and unit tests for apply_filters_from_args covering both forms. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for repeating --filter on the export command while preserving backward-compatible parsing of legacy &-joined filter pairs.
Changes:
- Update export CLI arg parsing to accept multiple
--filterflags (action="append"). - Implement back-compat filter splitting when a single
--filtercontains&. - Add/extend tests for parser behavior and filter application; update help text to document new usage.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/parsers/test_parser_export.py | Adds tests validating --filter repeatability and default behavior. |
| tests/commands/test_datasources_and_workbooks_command.py | Adds unit tests for applying parsed filters into TSC request options, including back-compat. |
| tabcmd/locales/en/tabcmd_messages_en.properties | Expands the --filter help text to document the new repeatable flag semantics and back-compat. |
| tabcmd/commands/datasources_and_workbooks/export_command.py | Changes --filter arg to append and updates filter parsing logic accordingly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
All call sites pass logger explicitly, so the default was unreachable. Tightens the type from Optional[Logger] to Logger, drops any fallback branch inside. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The updated filter-path still risks truncating values containing = and can error on ambiguous single-flag & splits unless parsing is made more robust (and covered by a regression test).
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
tabcmd/commands/datasources_and_workbooks/export_command.py:150
apply_filters_from_argscurrently claims repeated flags allow literal '&' or '=' inside values, but the implementation delegates toDatasourcesAndWorkbooks.apply_filter_value, which splits on every '=' and will truncate values likeNotes=x=y. Also, the back-compat single-flag split on '&' can yield fragments without '=', which can raiseIndexErrordownstream. Consider parsingCOLUMN=VALUEhere withsplit('=', 1)and only treating '&' as a delimiter when every segment contains '=' (otherwise treat '&' as literal and warn) to avoid crashes and preserve values.
tests/commands/test_datasources_and_workbooks_command.py:217- Current tests cover '&' in values, but they don't assert the stated behavior that '=' inside a filter value is preserved (e.g.
Notes=x=y). Adding a regression test would catch truncation bugs in filter parsing.
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Motivation
--filterpreviously accepted one value and required multi-pair filtersto be joined with
&. That parsing scheme prevents literal&inside avalue (e.g.
Product Name=AT&Tgets split). Making--filterrepeatable removes the need for callers to encode delimiters.
Related to #442, which handles the same problem when the filter comes in
via URL syntax rather than the flag.
Behavior change
For users:
--filteris now repeatable. Each flag carries exactlyone
COLUMN=VALUEpair.Back-compat: when only one
--filteris present, the value is stillsplit on
&. This means a single flag carrying one filter with&inits value (e.g.
--filter "Product=AT&T"alone) is still ambiguous.Workaround: pass the filter in the URL query string instead of via
--filter. #442 landed the URL-path handling for literal&, sotabcmd get "views/View/Sheet.csv?Product%20Name=AT&T%20841000%20Phone"works correctly (space must be encoded as
%20;&may be literal).Test plan
pytest tests/commands/test_datasources_and_workbooks_command.py tests/parsers/test_parser_export.py— 34 passed--filterwith&in the value returns theexpected row
&-joined form still parses and filterscorrectly
🤖 Generated with Claude Code