Skip to content

Conversation

owlas
Copy link

@owlas owlas commented Jul 14, 2025

Summary

This PR fixes #15 by implementing proper boolean parsing in the LKML parser. Boolean values like yes, no, true, and false are now correctly converted to Python bool objects instead of remaining as strings.

Changes

Core Implementation

  • Modified DictVisitor.visit_token() in lkml/simple.py to:

    • Check if token is quoted (using QuotedSyntaxToken) - if so, preserve as string
    • Convert unquoted boolean strings (yes/no/true/false) to Python bool objects
    • Handle case-insensitive matching for boolean values
  • Updated DictParser.parse_any() to handle boolean type during serialization:

    • Added bool to accepted types
    • Convert Python booleans back to yes/no for LKML output

Test Coverage

Added comprehensive tests in tests/test_simple.py:

  • test_boolean_parsing_yes_no - Basic yes/no conversion
  • test_boolean_parsing_true_false - Basic true/false conversion
  • test_boolean_parsing_case_insensitive - Case insensitive handling
  • test_boolean_parsing_non_boolean_strings - Non-boolean strings remain unchanged
  • test_boolean_round_trip - Round-trip serialization works correctly
  • test_quoted_boolean_strings_remain_strings - Quoted values remain as strings
  • test_mixed_quoted_unquoted_booleans - Mixed quoted/unquoted in same structure
  • test_filter_with_quoted_boolean_values - Filter blocks with quoted booleans
  • test_case_sensitivity_with_quoted_values - Case preservation for quoted values
  • test_edge_cases_quoted_vs_unquoted - Edge cases and empty strings

Examples

Before (incorrect):

>>> import lkml
>>> parsed = lkml.load('view: test { dimension: field { hidden: yes } }')
>>> parsed['views'][0]['dimensions'][0]['hidden']
'yes'  # String, not boolean\!

After (correct):

>>> import lkml
>>> parsed = lkml.load('view: test { dimension: field { hidden: yes } }')
>>> parsed['views'][0]['dimensions'][0]['hidden']
True  # Proper Python boolean

>>> # Quoted values remain as strings
>>> parsed = lkml.load('view: test { dimension: field { label: "yes" } }')
>>> parsed['views'][0]['dimensions'][0]['label']
'yes'  # String, as expected

Behavior Summary

  • hidden: yesTrue (bool)
  • primary_key: noFalse (bool)
  • suggestions: trueTrue (bool)
  • can_filter: falseFalse (bool)
  • label: "yes""yes" (str)
  • value: "true""true" (str)
  • ✅ Case insensitive for unquoted values
  • ✅ Case preserved for quoted values
  • ✅ Round-trip serialization works correctly

Fixes #15

owlas added 2 commits July 14, 2025 20:44
This commit fixes issue joshtemple#15 by implementing proper boolean parsing in the LKML parser.

Changes:
- Modified DictVisitor.visit_token() to convert unquoted boolean strings (yes/no/true/false) to Python bool objects
- Preserved quoted boolean strings (e.g., "yes", "true") as string values
- Updated DictParser.parse_any() to handle boolean type during serialization
- Added comprehensive test coverage for boolean parsing scenarios

The parser now correctly:
- Converts `hidden: yes` to Python `True`
- Converts `primary_key: no` to Python `False`
- Preserves `label: "yes"` as string `"yes"`
- Handles case-insensitive boolean values (YES, No, TRUE, False)
- Supports round-trip serialization

Fixes joshtemple#15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Automatically convert yes/no to boolean
1 participant