Skip to content

codylandry/Smores

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Smores

PyPI PyPI CircleCI branch Coverage Status

Smores allows you to specify a schema for user facing template features. It leverages marshmallow (hence 'smores') to populate and transform data that is then rendered via jinja. It has a parser that presents a more friendly syntax to users (ex. {user.addresses:1.street}). It also includes an autocomplete method that gives you intellisense style options given a tag fragment.

Smores provides two Marshmallow field types called TemplateString and TemplateFile. Templates defined in these fields are scoped to that schema and it's descendants. Each schema can have a _default_template that, if defined, will what is inserted if the associated tag ends with that schema. For example: typing {user.address} will render the _default_template for the Address schema. You can define other template attributes as well. For example, see the 'google_link' attribute of the Address schema below. Typing {user.address.google_link} will populate and insert that link.

smores.tag_autocomplete is a method where you can provide a tag 'fragment' and it will return the possible options below that. For example:

from smores import Smores, TemplateString
from marshmallow import Schema, fields

# instantiate a smores instance
smores = Smores()

# smores.schema registers the schema with the instance
@smores.schema
class Coordinates(Schema):
    lat = fields.Decimal()
    lng = fields.Decimal()
    _default_template = TemplateString("{{lat}},{{lng}}")

@smores.schema
class Address(Schema):
    street = fields.String()
    suite = fields.String()
    city = fields.String()
    state = fields.String()
    zipcode = fields.String()
    coordinates = fields.Nested(Coordinates)
    google_link = TemplateString('<a href="https://maps.google.com/?ll={{coordinates}}">View Map</a>')
    _default_template = TemplateString("""
        <div>{{<a href="https://maps.google.com/?ll={{coordinates}}">View Map</a>}}</div>
        <div>{{street}} -- {{suite}}</div>
        <div>{{city}}, {{state}} {{zipcode}}</div>
    """)

@smores.schema
class User(Schema):
    id = fields.Integer()
    name = fields.String()
    email = fields.Email()
    address = fields.Nested(Address)
    _default_template = TemplateString("""
        <div>{{name}}</div>
        <div>E: {{email}}</div>
        <div>{{address}}</div>
    """)
# for the schemas above, simply invoke the autocomplete method with a tag fragment

>>> smores.autocomplete("")
AutocompleteResponse(tagStatus='INVALID', options=['address', 'coordinates', 'user'])

>>> smores.autocomplete('user')
AutocompleteResponse(tagStatus='VALID', options=['_default_template', 'address', 'email', 'id', 'name'])

>>> smores.autocomplete('us')
AutocompleteResponse(tagStatus='INVALID', options=['user'])

>>> smores.autocomplete("user.address.coordinates")
AutocompleteResponse(tagStatus='VALID', options=['_default_template', 'lat', 'lng'])

# Receiving '_default_template' or no results means that the current tag fragment is valid but _default_template
# shouldn't be appended to the tag in the ui.
# provide data to the render function
data = {
    "user": {
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "[email protected]",
        "phone": "1-770-736-8031 x56442",
        "address": {
            "street": "Kulas Light",
            "suite": "Apt. 556",
            "city": "Gwenborough",
            "state": "MD",
            "zipcode": "92998-3874",
            "coordinates": {
                "lat": "36.065934",
				"lng": "-79.791414"
            }
        },
    }
}

# provide user created template
user_template = """
    <h3>Hi, {user.name}!</h3>
    <p>Your Info:</p>
    {user}
"""

# render the output
print smores.render(data, user_template)

# output -->
# <h3>Hi, Leanne Graham!</h3>
# <p>Your Info:</p>
# 
# <div>Leanne Graham</div>
# <div>E: [email protected]</div>
# <div>
#     <div><a href="https://maps.google.com/?ll=36.065934,-79.791414">View Map</a></div>
#     <div>Kulas Light -- Apt. 556</div>
#     <div>Gwenborough, MD 92998-3874</div>
# </div>