Skip to content

feat: add OR-condition support for search/filter syntax#38

Merged
BigLep merged 7 commits into
masterfrom
004-or-filter-syntax
May 8, 2026
Merged

feat: add OR-condition support for search/filter syntax#38
BigLep merged 7 commits into
masterfrom
004-or-filter-syntax

Conversation

@BigLep
Copy link
Copy Markdown
Contributor

@BigLep BigLep commented May 6, 2026

Background

I wanted this because for weekly reporting I want to pull open issues and recently completed:

{
  "projectUrl": "https://github.com/orgs/FilOzone/projects/14",
  "queryParts": [
    "is:issue",
    "(",
    "-status:\"🎉 Done\"",
    "milestone:\"M4.2: mainnet GA\"",
    ") OR (",
    "-last-updated:7days",
    ")"
  ],
  "fields": [
    "Repository",
    "Id",
    "url",
    "Title",
    "Status",
    "Kind",
    "Milestone",
    "Assignees",
    "Reviewers",
    "Cycle Theme",
    "Dev Days Estimate"
  ]
}

Summary

  • Add expand_or_query() parser in github-projects-client that expands shared-prefix OR syntax (prefix (branch1) OR (branch2)) into multiple individual queries
  • Integrate OR expansion into export_rows() (github-project-export) and list_items() (github-projects-client/MCP server) with deduplication by item ID
  • Validate OR syntax at config load time, surfacing clear error messages for malformed expressions
  • Add comprehensive test coverage: 23 parser unit tests, 8 config validation tests, 2 OR integration tests, 1 golden-file export test

Details

Each OR branch becomes a separate REST API query; results are union-merged with deduplication (by item["id"] for raw items, _node_id for formatted items). The parser is a pure function in the shared client library so both the export tool and MCP server benefit.

Syntax: shared-prefix (branch-1) OR (branch-2) OR (branch-3)

Limitations (documented in README): single-level OR only — no nested parens, no AND keyword, no trailing terms after last group.

Test plan

  • Parser unit tests pass (23 cases): cd github-projects-client && uv run pytest tests/test_query_unit.py -v
  • Config validation tests pass (8 cases): cd github-project-export && uv run pytest tests/test_config_validation.py -v
  • Client integration tests pass (30 cases including 2 new OR tests): cd github-projects-client && GITHUB_TOKEN=$(gh auth token) uv run pytest -v
  • Export integration tests pass (2 golden-file tests): cd github-project-export && GITHUB_TOKEN=$(gh auth token) uv run pytest -v
  • Backward compatibility verified: all existing tests pass unchanged
  • Manual test with real OR config (m4.2.config.json) produces correct output

🤖 Generated with Claude Code

BigLep and others added 4 commits May 6, 2026 11:10
Implement shared-prefix OR query expansion across github-projects-client
and github-project-export. Each OR branch becomes a separate API query
with results union-merged and deduplicated by item ID. The parser lives
in the shared client library so both the export tool and MCP server
(via list_items) get OR support automatically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@FilOzzy FilOzzy added this to FOC May 6, 2026
@github-project-automation github-project-automation Bot moved this to 📌 Triage in FOC May 6, 2026
Remove unused tempfile import and apply ruff formatting to query.py
and test_query_unit.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BigLep BigLep requested review from Copilot and rjan90 May 6, 2026 19:08
@BigLep BigLep self-assigned this May 6, 2026
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting review in FOC May 6, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 4 comments.

Comment on lines +80 to +97
# Check for OR keyword (outside quotes, outside parens)
if paren_depth == 0 and ch in ("O", "o") and query[i : i + 2] == "OR":
# Ensure OR is whitespace-bounded
before_ok = (i == 0) or query[i - 1] in (" ", "\t")
after_ok = (i + 2 >= n) or query[i + 2] in (" ", "\t")
if before_ok and after_ok:
found_or = True
token = "".join(current).strip()
if token:
# Text before OR that's not in a group — means OR without parens
if not found_parens:
raise ValueError("OR requires parenthesized groups")
raise ValueError(
"Filter terms after the last group are not allowed"
)
current = []
i += 2
continue
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in d319975. Added expect_group and expect_or state tracking:

  • (a) OR now raises "OR must be followed by a parenthesized group"
  • (a) (b) now raises "Expected OR between groups; consecutive groups require OR"

Added unit tests for both cases.

Comment thread github-projects-client/github_projects_client/query.py Outdated
Comment thread github-projects-client/github_projects_client/items.py Outdated
Comment thread github-projects-client/tests/test_integration.py Outdated
- Add expect_group/expect_or state tracking to reject trailing OR
  without a following group and consecutive groups without OR between
- Fix unmatched quote error message (was incorrectly saying 'Unmatched
  opening parenthesis')
- Use _extract_node_id() helper for dedup in list_items() OR path to
  avoid mixed str/int keys
- Fix integration test to assert items from both M4.0 and M4.1
  milestones (was checking wrong milestone)
- Add 3 new unit tests for the new error conditions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rjan90 rjan90 added this to the M4.2: mainnet GA milestone May 8, 2026
Comment thread github-projects-client/github_projects_client/items.py
OR queries fetch all matching items in a single request, so cursor-based
pagination doesn't apply. Passing a cursor now raises ValueError. Added a
configurable max_or_items parameter (default 1000) to prevent runaway
queries from overwhelming the server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@BigLep
Copy link
Copy Markdown
Contributor Author

BigLep commented May 8, 2026

I'm going to merge since incorporated feedback and want to get this in before kick off other refactoring.

@BigLep BigLep merged commit abf689a into master May 8, 2026
5 checks passed
@github-project-automation github-project-automation Bot moved this from 🔎 Awaiting review to 🎉 Done in FOC May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🎉 Done

Development

Successfully merging this pull request may close these issues.

4 participants