OLD | NEW |
1 # Copyright 2012 Benjamin Kalman | 1 # Copyright 2012 Benjamin Kalman |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 def Render(self, render_state): | 636 def Render(self, render_state): |
637 value = render_state.contexts.Resolve(self._id.name) | 637 value = render_state.contexts.Resolve(self._id.name) |
638 if value is None: | 638 if value is None: |
639 render_state.AddResolutionError(self._id) | 639 render_state.AddResolutionError(self._id) |
640 return | 640 return |
641 render_state.text.Append(json.dumps(value, separators=(',',':'))) | 641 render_state.text.Append(json.dumps(value, separators=(',',':'))) |
642 | 642 |
643 def __repr__(self): | 643 def __repr__(self): |
644 return '{{*%s}}' % self._id | 644 return '{{*%s}}' % self._id |
645 | 645 |
| 646 class _PartialNodeWithArguments(_DecoratorNode): |
| 647 def __init__(self, partial, args): |
| 648 if isinstance(partial, Handlebar): |
| 649 # Preserve any get() method that the caller has added. |
| 650 if hasattr(partial, 'get'): |
| 651 self.get = partial.get |
| 652 partial = partial._top_node |
| 653 _DecoratorNode.__init__(self, partial) |
| 654 self._partial = partial |
| 655 self._args = args |
| 656 |
| 657 def Render(self, render_state): |
| 658 render_state.contexts.Scope(self._args, self._partial.Render, render_state) |
| 659 |
646 class _PartialNode(_LeafNode): | 660 class _PartialNode(_LeafNode): |
647 '''{{+var:foo}} ... {{/foo}} | 661 '''{{+var:foo}} ... {{/foo}} |
648 ''' | 662 ''' |
649 def __init__(self, bind_to, id_, content): | 663 def __init__(self, bind_to, id_, content): |
650 _LeafNode.__init__(self, id_.line, id_.line) | 664 _LeafNode.__init__(self, id_.line, id_.line) |
651 self._bind_to = bind_to | 665 self._bind_to = bind_to |
652 self._id = id_ | 666 self._id = id_ |
653 self._content = content | 667 self._content = content |
654 self._resolved_args = None | |
655 self._args = None | 668 self._args = None |
656 self._pass_through_id = None | 669 self._pass_through_id = None |
657 | 670 |
658 @classmethod | 671 @classmethod |
659 def Inline(cls, id_): | 672 def Inline(cls, id_): |
660 return cls(None, id_, None) | 673 return cls(None, id_, None) |
661 | 674 |
662 def Render(self, render_state): | 675 def Render(self, render_state): |
663 value = render_state.contexts.Resolve(self._id.name) | 676 value = render_state.contexts.Resolve(self._id.name) |
664 if value is None: | 677 if value is None: |
665 render_state.AddResolutionError(self._id) | 678 render_state.AddResolutionError(self._id) |
666 return | 679 return |
667 if not isinstance(value, (Handlebar, _Node)): | 680 if not isinstance(value, (Handlebar, _Node)): |
668 render_state.AddResolutionError(self._id, description='not a partial') | 681 render_state.AddResolutionError(self._id, description='not a partial') |
669 return | 682 return |
670 | 683 |
671 if isinstance(value, Handlebar): | 684 if isinstance(value, Handlebar): |
672 node, name = value._top_node, value._name | 685 node, name = value._top_node, value._name |
673 else: | 686 else: |
674 node, name = value, None | 687 node, name = value, None |
675 | 688 |
676 partial_render_state = render_state.ForkPartial(name, self._id) | 689 partial_render_state = render_state.ForkPartial(name, self._id) |
677 | 690 |
678 arg_context = {} | 691 arg_context = {} |
679 if self._pass_through_id is not None: | 692 if self._pass_through_id is not None: |
680 context = render_state.contexts.Resolve(self._pass_through_id.name) | 693 context = render_state.contexts.Resolve(self._pass_through_id.name) |
681 if context is not None: | 694 if context is not None: |
682 arg_context[self._pass_through_id.name] = context | 695 arg_context[self._pass_through_id.name] = context |
683 if self._resolved_args is not None: | |
684 arg_context.update(self._resolved_args) | |
685 if self._args is not None: | 696 if self._args is not None: |
686 def resolve_args(args): | 697 def resolve_args(args): |
687 resolved = {} | 698 resolved = {} |
688 for key, value in args.iteritems(): | 699 for key, value in args.iteritems(): |
689 if isinstance(value, dict): | 700 if isinstance(value, dict): |
690 assert len(value.keys()) == 1 | 701 assert len(value.keys()) == 1 |
691 inner_id, inner_args = value.items()[0] | 702 id_of_partial, partial_args = value.items()[0] |
692 inner_partial = render_state.contexts.Resolve(inner_id.name) | 703 partial = render_state.contexts.Resolve(id_of_partial.name) |
693 if inner_partial is not None: | 704 if partial is not None: |
694 context = _PartialNode(None, inner_id, inner_partial) | 705 resolved[key] = _PartialNodeWithArguments( |
695 context.SetResolvedArguments(resolve_args(inner_args)) | 706 partial, resolve_args(partial_args)) |
696 resolved[key] = context | |
697 else: | 707 else: |
698 context = render_state.contexts.Resolve(value.name) | 708 context = render_state.contexts.Resolve(value.name) |
699 if context is not None: | 709 if context is not None: |
700 resolved[key] = context | 710 resolved[key] = context |
701 return resolved | 711 return resolved |
702 arg_context.update(resolve_args(self._args)) | 712 arg_context.update(resolve_args(self._args)) |
703 if self._bind_to and self._content: | 713 if self._bind_to and self._content: |
704 arg_context[self._bind_to.name] = self._content | 714 arg_context[self._bind_to.name] = self._content |
705 if arg_context: | 715 if arg_context: |
706 partial_render_state.contexts.Push(arg_context) | 716 partial_render_state.contexts.Push(arg_context) |
707 | 717 |
708 node.Render(partial_render_state) | 718 node.Render(partial_render_state) |
709 | 719 |
710 render_state.Merge( | 720 render_state.Merge( |
711 partial_render_state, | 721 partial_render_state, |
712 text_transform=lambda text: text[:-1] if text.endswith('\n') else text) | 722 text_transform=lambda text: text[:-1] if text.endswith('\n') else text) |
713 | 723 |
714 def SetResolvedArguments(self, args): | |
715 self._resolved_args = args | |
716 | |
717 def SetArguments(self, args): | 724 def SetArguments(self, args): |
718 self._args = args | 725 self._args = args |
719 | 726 |
720 def PassThroughArgument(self, id_): | 727 def PassThroughArgument(self, id_): |
721 self._pass_through_id = id_ | 728 self._pass_through_id = id_ |
722 | 729 |
723 def __repr__(self): | 730 def __repr__(self): |
724 return '{{+%s}}' % self._id | 731 return '{{+%s}}' % self._id |
725 | 732 |
726 _TOKENS = {} | 733 _TOKENS = {} |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 id_ = _Identifier(tokens.AdvanceOverNextString(excluded=' \n\r\t:()'), | 1092 id_ = _Identifier(tokens.AdvanceOverNextString(excluded=' \n\r\t:()'), |
1086 tokens.next_line, | 1093 tokens.next_line, |
1087 column_start) | 1094 column_start) |
1088 tokens.SkipWhitespace() | 1095 tokens.SkipWhitespace() |
1089 return id_ | 1096 return id_ |
1090 | 1097 |
1091 def Render(self, *user_contexts): | 1098 def Render(self, *user_contexts): |
1092 '''Renders this template given a variable number of contexts to read out | 1099 '''Renders this template given a variable number of contexts to read out |
1093 values from (such as those appearing in {{foo}}). | 1100 values from (such as those appearing in {{foo}}). |
1094 ''' | 1101 ''' |
1095 name = self._name or '<root>' | |
1096 internal_context = _InternalContext() | 1102 internal_context = _InternalContext() |
1097 render_state = _RenderState( | 1103 contexts = list(user_contexts) |
1098 name, _Contexts([{'_': internal_context}] + list(user_contexts))) | 1104 contexts.append({ |
| 1105 '_': internal_context, |
| 1106 'false': False, |
| 1107 'true': True, |
| 1108 }) |
| 1109 render_state = _RenderState(self._name or '<root>', _Contexts(contexts)) |
1099 internal_context.SetRenderState(render_state) | 1110 internal_context.SetRenderState(render_state) |
1100 self._top_node.Render(render_state) | 1111 self._top_node.Render(render_state) |
1101 return render_state.GetResult() | 1112 return render_state.GetResult() |
1102 | 1113 |
1103 def render(self, *contexts): | 1114 def render(self, *contexts): |
1104 return self.Render(*contexts) | 1115 return self.Render(*contexts) |
1105 | 1116 |
1106 def __eq__(self, other): | 1117 def __eq__(self, other): |
1107 return self.source == other.source and self._name == other._name | 1118 return self.source == other.source and self._name == other._name |
1108 | 1119 |
1109 def __ne__(self, other): | 1120 def __ne__(self, other): |
1110 return not (self == other) | 1121 return not (self == other) |
1111 | 1122 |
1112 def __repr__(self): | 1123 def __repr__(self): |
1113 return str('%s(%s)' % (type(self).__name__, self._top_node)) | 1124 return str('%s(%s)' % (type(self).__name__, self._top_node)) |
1114 | 1125 |
1115 def __str__(self): | 1126 def __str__(self): |
1116 return repr(self) | 1127 return repr(self) |
OLD | NEW |