noahmorrison / chevron

A Python implementation of mustache
MIT License
486 stars 52 forks source link

Suggestion: Adding a 'replacer' function, like in JSON.stringify() #35

Closed talamus closed 5 years ago

talamus commented 5 years ago

Hello, Could it be possible to have an optional replacer function for the values, like the one in JSON.stringify()?

Our problem is that our booleans are getting written out as "True" and "False" when the template we are writing them expects them to be in "true" and "false" format.

Of course -- the same thing could be used to convert datetime objects into some specific format, like these beautifully ugly "/Date(1239018869048)/" .Net things.

noahmorrison commented 5 years ago

Short answer: suuuuuuure, but not really

Long answer: I feel like this would be better handled outside of chevron. Before today, chevron could almost do this with just a simple custom datatype, but I needed to add just a few lines of code in order to get custom falsy data types to output as something besides empty strings.

Here's an example of how to do this outside of chevron

#!/usr/bin/env python
import chevron

class CustomData(dict):
    class LowercaseBool:
        _CHEVRON_return_scope_when_falsy = True

        def __init__(self, value):
            self.value = value

        def __bool__(self):
            return self.value
        __nonzero__ = __bool__

        def __str__(self):
            if self.value:
                return 'true'
            return 'false'

    def __getitem__(self, key):
        item = dict.__getitem__(self, key)
        if isinstance(item, dict):
            return CustomData(item)
        if isinstance(item, bool):
            return self.LowercaseBool(item)
        return item

data = { 
    'truthy': True,
    'falsy': False,
}

template = '''\
{{# truthy}}
Truthy is {{ truthy }} and Falsy is {{ falsy }}
{{/ truthy}}
{{# falsy }}
This will never print {{.}}
{{/ falsy }}
'''

print(chevron.render(template, CustomData(data)))
# Truthy is true and Falsy is false

You should be able to convert datetime objects in a similar fashion too, all of this with no extra logic inside of chevron, and no (well, very little, I had to add those lines in) overhead unless you want to do this.

I hope this does what you need it to, if not let me know. I'm not opposed to chevron becoming better, I just want to make sure chevron stays spec compliant, compatible with old versions of python, and fast.

I'll release a version with this soonish, I want to checkout some of the other issues and PRs first (If I don't, just comment here or email me and yell at me).

talamus commented 5 years ago

Excellent! Much better idea that I was going to hack together.

(I had a small worry about the truthiness of the "false" string, but then I read your code sample with open eyes. The value and the string representation are separated in there.)

noahmorrison commented 5 years ago

Hey talamus,

This is works except for the looping over lists, just have to expand CustomData a bit... https://gist.github.com/noahmorrison/4810ee5cf33f694da2449952b9205809

(please let me know if you got this email, not 100% sure it'll get to you)

Noah

On Fri, Aug 24, 2018 at 8:28 AM, Tero Niemi notifications@github.com wrote:

Now when I think about this -- there is a possibility this approach can create a small problem, because the "false" (a string) is actually True.

Consider some JSON data:

{ "entities": [ { "type": "dog", "mythical": false },{ "type": "kerberos", "mythical": true } ], "this_is_null": null }

And a template:

{{#entities}} type: {{type}} mythical: {{mythical}} {{#mythical}} "A truly mythical creature!" {{/mythical}} {{^mythical}} "An ordinary animal" {{/mythical}} {{/entities}}

The desired output would be:

type: dog mythical: false "An ordinary animal" type: kerberos mythical: true "A truly mythical creature!"

Note the small case "true" and "false" combined with working boolean logic. (The same thing would happen if someone would like to output None as "null".)

I think we are going to need a separate getValue() and toString(), so to speak...

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/noahmorrison/chevron/issues/35#issuecomment-415744145, or mute the thread https://github.com/notifications/unsubscribe-auth/AHEujWaez3TYicuu2rjQRKu0XI1ZXLFfks5uT_FZgaJpZM4WJm7m .