Skip to content

Commit

Permalink
allow for reading yaml from string
Browse files Browse the repository at this point in the history
  • Loading branch information
jbogaardt committed Apr 5, 2020
1 parent 2e3f220 commit 021b162
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 31 deletions.
28 changes: 14 additions & 14 deletions docs/templating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The python object above can be expressed in a YAML notation and read into
**Example:**
>>> my_template = """
... - Column:
... Title:
... - Title:
... data: ['This is a', 'sample title']
... formats:
... align: 'left'
Expand All @@ -41,7 +41,7 @@ using jinja, we can insert data into our template.
**Example:**
>>> my_template = """
... - Column:
... Title:
... - Title:
... data: ['This is a', {{title}}]
... formats:
... align: 'left'
Expand Down Expand Up @@ -70,10 +70,10 @@ variable, jinja will grab the string representation of the object.
**This will not work:**
>>> my_template = """
... - Column:
... Title:
... - Title:
... data: ['This is a', 'sample title']
... DataFrame:
... data: {{data}}
... - DataFrame:
... data: {{data}}
... """
>>> xlc.load_yaml(my_template, data=data)

Expand All @@ -90,10 +90,10 @@ We don't want the string representation of our `DataFrame`, we want the actual
**This is correct:**
>>> my_template = """
... - Column:
... Title:
... - Title:
... data: ['This is a', 'sample title']
... DataFrame:
... data: {% eval %}data{% endeval %}
... - DataFrame:
... data: {% eval %}data{% endeval %}
... """
>>> xlc.load_yaml(my_template, data=data)

Expand All @@ -109,10 +109,10 @@ pass other variables as context to your `eval` directive.
**Example:**
>>> my_template = """
... - Column:
... Title:
... - Title:
... data: ['This is a', 'sample title']
... DataFrame:
... data: {% eval %}data.groupby('{{group}}').sum(){% endeval %}
... - DataFrame:
... data: {% eval %}data.groupby('{{group}}').sum(){% endeval %}
... """
>>> xlc.load_yaml(my_template, data=data, group='country')

Expand All @@ -129,14 +129,14 @@ revenue and expense by product.
**Example:**
>>> my_template = """
... - Column:
... Title:
... - Title:
... data: ['Summary of Revenue and Expense', 'By Product and Country']
... {% for country in data['country'].unique() %}
... Series:
... - Series:
... data: 'Revenue and Expense for {{country}}'
... formats:
... bold: True
... DataFrame:
... - DataFrame:
... data: {% eval %}data.groupby({{country}})[['Revenue', 'Expense']].sum(){% endeval %}
... formats:
... align: 'center'
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
descr = "A declarative API for composing spreadsheets from python"
name = 'xlcompose'
url = 'https://github.com/jbogaardt/xlcompose'
version='0.2.0' # Put this in __init__.py
version='0.2.1' # Put this in __init__.py

data_path = ''
setup(
Expand Down
2 changes: 1 addition & 1 deletion xlcompose/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.2.0'
__version__ = '0.2.1'
from xlcompose.core import (
Tabs, Sheet, Row, Column,
DataFrame, Series, CSpacer, RSpacer, Title, Image, VSpacer, HSpacer)
Expand Down
38 changes: 23 additions & 15 deletions xlcompose/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import ast
import os
import xlcompose.core as core
from jinja2 import nodes, Template, TemplateSyntaxError, FileSystemLoader, Environment
from jinja2 import nodes, Template, TemplateSyntaxError, FileSystemLoader, Environment, BaseLoader
from jinja2.ext import Extension
from jinja2.nodes import Const

Expand All @@ -28,7 +28,7 @@ def _eval(self, eval_str, caller):
return '__eval__' + caller() + '__eval__'


def kwarg_parse(formula):
def _kwarg_parse(formula):
names = pd.Series(list(set([node.id for node in ast.walk(ast.parse(formula))
if isinstance(node, ast.Name)])))
names = names[~names.isin(['str', 'list', 'dict', 'int', 'float'])]
Expand All @@ -41,39 +41,47 @@ def kwarg_parse(formula):
formula = formula.replace(item[1],item[2])
return formula

def make_xlc(template, **kwargs):
def _make_xlc(template, **kwargs):
""" Recursively generate xlcompose object"""
if type(template) is list:
tabs = [make_xlc(element, **kwargs) for element in template]
return core.Tabs(*[(item.name, item) for item in tabs])
tabs = [_make_xlc(element, **kwargs) for element in template]
try:
return core.Tabs(*[(item.name, item) for item in tabs])
except:
return core.Tabs(*[('Sheet1', item) for item in tabs])
key = list(template.keys())[0]
if key in ['Row', 'Column']:
return getattr(core, key)(*[make_xlc(element, **kwargs)
return getattr(core, key)(*[_make_xlc(element, **kwargs)
for element in template[key]])
if key in ['Sheet']:
sheet_kw = {k: v for k, v in template[key].items()
if k not in ['name', 'layout']}
return core.Sheet(template[key]['name'],
make_xlc(template[key]['layout'], **kwargs),
_make_xlc(template[key]['layout'], **kwargs),
**sheet_kw)
if key in ['DataFrame', 'Title', 'CSpacer', 'RSpacer', 'HSpacer',
'Series', 'Image']:
for k, v in template[key].items():
if type(v) is str:
if v[:8] == '__eval__':
v_adj = v.replace('__eval__', '')
template[key][k] = eval(kwarg_parse(v_adj))
template[key][k] = eval(_kwarg_parse(v_adj))
return getattr(core, key)(**template[key])

def load(template, env, kwargs):
if env:
env.add_extension(EvalExtension)
else:
path = os.path.dirname(os.path.abspath(template))
template = os.path.split(os.path.abspath(template))[-1]
env = Environment(loader=FileSystemLoader(path))
env.add_extension(EvalExtension)
template = env.get_template(template).render(kwargs)
try:
path = os.path.dirname(os.path.abspath(template))
template = os.path.split(os.path.abspath(template))[-1]
env = Environment(loader=FileSystemLoader(path))
env.add_extension(EvalExtension)
template = env.get_template(template).render(kwargs)
except:
env = Environment(loader=BaseLoader())
env.add_extension(EvalExtension)
template = env.from_string(template).render(kwargs)
replace = [item.strip() for item in re.findall('[ :]{{.+}}', template)]
for item in replace:
template = template.replace(item, '\'' + item + '\'')
Expand All @@ -84,10 +92,10 @@ def load_yaml(template, env=None, **kwargs):
""" Loads a YAML template specifying the structure of the XLCompose Object.
"""
template = load(template, env, kwargs)
return make_xlc(yaml.load(template, Loader=yaml.SafeLoader), **kwargs)
return _make_xlc(yaml.load(template, Loader=yaml.SafeLoader), **kwargs)

def load_json(template, env=None, **kwargs):
""" Loads a JSON template specifying the structure of the XLCompose Object.
"""
template = load(template, env, kwargs)
return make_xlc(json.loads(template), **kwargs)
return _make_xlc(json.loads(template), **kwargs)

0 comments on commit 021b162

Please sign in to comment.