dmulyalin / ttp

Template Text Parser
MIT License
350 stars 34 forks source link

Inconsistent result from group #34

Closed james-powis closed 4 years ago

james-powis commented 4 years ago

There should be a way to force a group to always return a list of dictionaries. As it stands now if a group only matches once it returns a dictionary of dictionary. In my usecase, I am writing router automated testing, the expectation of the code is to always receive the same data-structure in this example a list (even if empty).

template = '''
<group name='demo'>
<group name='audiences'>
Hello {{ audience }}
</group>
</group>
'''

input_1 = '''
Hello World
'''

input_2 = '''
Hello World
Hello Family
'''

The results:

result_1 = [
    [
        {
            "demo": {
                "audiences": {
                    "audience": "World"
                }
            }
        }
    ]
]

result_2 = [
    [
        {
            "demo": {
                "audiences": [
                    {
                        "audience": "World"
                    },
                    {
                        "audience": "Family"
                    }
                ]
            }
        }
    ]
]
dmulyalin commented 4 years ago

Check out https://ttp.readthedocs.io/en/latest/Forming%20Results%20Structure/Path%20formatters.html#path-formatters

james-powis commented 4 years ago

Low and behold the answer! Thanks @dmulyalin

For future readers of this issue:

template:

<group name='demo'>
<group name='audiences*'>
Hello {{ audience }}
</group>
</group>

input:

Hello World

result:

[
    [
        {
            "demo": {
                "audiences": [
                    {
                        "audience": "World"
                    }
                ]
            }
        }
    ]
]

@dmulyalin is there a way to force ttp to create empty scaffolding when a group or value is not matched?

Imagine an input of hellos world a desired return would be:

[
    [
        {
            "demo": {
                "audiences": []
            }
        }
    ]
]

In my use case, this would save having to check if key audiences exists prior to diving into it with a for loop.

dmulyalin commented 4 years ago

Hi, thanks for asking, turns out forgot to document it. You can use match variable default function to define default value. Not the exact match to what you asking for, but still something. Have plans to add support for group defaults to reference structures defined in template variables, that would allow to define exactly what you need.

This template:

<input load="text">
Hi World
</input>

<group name='demo'>
<group name='audiences*'>
Hello {{ audience | default([]) }}
</group>
</group>

will produce: [[{'demo': {'audiences': [{'audience': []}]}}]]