def _calculate(self, a, b, t): _calculate = self._calculate if isinstance(a, list) or isinstance(a, tuple): if isinstance(a, list): tp = list else: tp = tuple return tp([_calculate(a[x], b[x], t) for x in range(len(a))]) elif isinstance(a, dict): d = {} for x in iterkeys(a): if x not in b: # User requested to animate only part of the dict. # Copy the rest d[x] = a[x] else: d[x] = _calculate(a[x], b[x], t) return d else: return (a * (1. - t)) + (b * t)
def _apply_rule(self, widget, rule, rootrule, template_ctx=None, ignored_consts=set()): # widget: the current instantiated widget # rule: the current rule # rootrule: the current root rule (for children of a rule) # will collect reference to all the id in children assert(rule not in self.rulectx) self.rulectx[rule] = rctx = { 'ids': {'root': widget.proxy_ref}, 'set': [], 'hdl': []} # extract the context of the rootrule (not rule!) assert(rootrule in self.rulectx) rctx = self.rulectx[rootrule] # if a template context is passed, put it as "ctx" if template_ctx is not None: rctx['ids']['ctx'] = QueryDict(template_ctx) # if we got an id, put it in the root rule for a later global usage if rule.id: # use only the first word as `id` discard the rest. rule.id = rule.id.split('#', 1)[0].strip() rctx['ids'][rule.id] = widget.proxy_ref # set id name as a attribute for root widget so one can in python # code simply access root_widget.id_name _ids = dict(rctx['ids']) _root = _ids.pop('root') _new_ids = _root.ids for _key in iterkeys(_ids): if _ids[_key] == _root: # skip on self continue _new_ids[_key] = _ids[_key] _root.ids = _new_ids # first, ensure that the widget have all the properties used in # the rule if not, they will be created as ObjectProperty. rule.create_missing(widget) # build the widget canvas if rule.canvas_before: with widget.canvas.before: self._build_canvas(widget.canvas.before, widget, rule.canvas_before, rootrule) if rule.canvas_root: with widget.canvas: self._build_canvas(widget.canvas, widget, rule.canvas_root, rootrule) if rule.canvas_after: with widget.canvas.after: self._build_canvas(widget.canvas.after, widget, rule.canvas_after, rootrule) # create children tree Factory_get = Factory.get Factory_is_template = Factory.is_template for crule in rule.children: cname = crule.name if cname in ('canvas', 'canvas.before', 'canvas.after'): raise ParserException( crule.ctx, crule.line, 'Canvas instructions added in kv must ' 'be declared before child widgets.') # depending if the child rule is a template or not, we are not # having the same approach cls = Factory_get(cname) if Factory_is_template(cname): # we got a template, so extract all the properties and # handlers, and push them in a "ctx" dictionary. ctx = {} idmap = copy(global_idmap) idmap.update({'root': rctx['ids']['root']}) if 'ctx' in rctx['ids']: idmap.update({'ctx': rctx['ids']['ctx']}) try: for prule in crule.properties.values(): value = prule.co_value if type(value) is CodeType: value = eval(value, idmap) ctx[prule.name] = value for prule in crule.handlers: value = eval(prule.value, idmap) ctx[prule.name] = value except Exception as e: tb = sys.exc_info()[2] raise BuilderException( prule.ctx, prule.line, '{}: {}'.format(e.__class__.__name__, e), cause=tb) # create the template with an explicit ctx child = cls(**ctx) widget.add_widget(child) # reference it on our root rule context if crule.id: rctx['ids'][crule.id] = child else: # we got a "normal" rule, construct it manually # we can't construct it without __no_builder=True, because the # previous implementation was doing the add_widget() before # apply(), and so, we could use "self.parent". child = cls(__no_builder=True) widget.add_widget(child) self.apply(child) self._apply_rule(child, crule, rootrule) # append the properties and handlers to our final resolution task if rule.properties: rctx['set'].append((widget.proxy_ref, list(rule.properties.values()))) for key, crule in rule.properties.items(): # clear previously applied rules if asked if crule.ignore_prev: Builder.unbind_property(widget, key) if rule.handlers: rctx['hdl'].append((widget.proxy_ref, rule.handlers)) # if we are applying another rule that the root one, then it's done for # us! if rootrule is not rule: del self.rulectx[rule] return # normally, we can apply a list of properties with a proper context try: rule = None for widget_set, rules in reversed(rctx['set']): for rule in rules: assert(isinstance(rule, ParserRuleProperty)) key = rule.name value = rule.co_value if type(value) is CodeType: value, bound = create_handler( widget_set, widget_set, key, value, rule, rctx['ids']) # if there's a rule if (widget_set != widget or bound or key not in ignored_consts): setattr(widget_set, key, value) else: if (widget_set != widget or key not in ignored_consts): setattr(widget_set, key, value) except Exception as e: if rule is not None: tb = sys.exc_info()[2] raise BuilderException(rule.ctx, rule.line, '{}: {}'.format(e.__class__.__name__, e), cause=tb) raise e # build handlers try: crule = None for widget_set, rules in rctx['hdl']: for crule in rules: assert(isinstance(crule, ParserRuleProperty)) assert(crule.name.startswith('on_')) key = crule.name if not widget_set.is_event_type(key): key = key[3:] idmap = copy(global_idmap) idmap.update(rctx['ids']) idmap['self'] = widget_set.proxy_ref if not widget_set.fbind(key, custom_callback, crule, idmap): raise AttributeError(key) # hack for on_parent if crule.name == 'on_parent': Factory.Widget.parent.dispatch(widget_set.__self__) except Exception as e: if crule is not None: tb = sys.exc_info()[2] raise BuilderException( crule.ctx, crule.line, '{}: {}'.format(e.__class__.__name__, e), cause=tb) raise e # rule finished, forget it del self.rulectx[rootrule]
def _apply_rule(self, widget, rule, rootrule, template_ctx=None, ignored_consts=set()): # widget: the current instantiated widget # rule: the current rule # rootrule: the current root rule (for children of a rule) # will collect reference to all the id in children assert (rule not in self.rulectx) self.rulectx[rule] = rctx = { 'ids': { 'root': widget.proxy_ref }, 'set': [], 'hdl': [] } # extract the context of the rootrule (not rule!) assert (rootrule in self.rulectx) rctx = self.rulectx[rootrule] # if a template context is passed, put it as "ctx" if template_ctx is not None: rctx['ids']['ctx'] = QueryDict(template_ctx) # if we got an id, put it in the root rule for a later global usage if rule.id: # use only the first word as `id` discard the rest. rule.id = rule.id.split('#', 1)[0].strip() rctx['ids'][rule.id] = widget.proxy_ref # set id name as a attribute for root widget so one can in python # code simply access root_widget.id_name _ids = dict(rctx['ids']) _root = _ids.pop('root') _new_ids = _root.ids for _key in iterkeys(_ids): if _ids[_key] == _root: # skip on self continue _new_ids[_key] = _ids[_key] _root.ids = _new_ids # first, ensure that the widget have all the properties used in # the rule if not, they will be created as ObjectProperty. rule.create_missing(widget) # build the widget canvas if rule.canvas_before: with widget.canvas.before: self._build_canvas(widget.canvas.before, widget, rule.canvas_before, rootrule) if rule.canvas_root: with widget.canvas: self._build_canvas(widget.canvas, widget, rule.canvas_root, rootrule) if rule.canvas_after: with widget.canvas.after: self._build_canvas(widget.canvas.after, widget, rule.canvas_after, rootrule) # create children tree Factory_get = Factory.get Factory_is_template = Factory.is_template for crule in rule.children: cname = crule.name if cname in ('canvas', 'canvas.before', 'canvas.after'): raise ParserException( crule.ctx, crule.line, 'Canvas instructions added in kv must ' 'be declared before child widgets.') # depending if the child rule is a template or not, we are not # having the same approach cls = Factory_get(cname) if Factory_is_template(cname): # we got a template, so extract all the properties and # handlers, and push them in a "ctx" dictionary. ctx = {} idmap = copy(global_idmap) idmap.update({'root': rctx['ids']['root']}) if 'ctx' in rctx['ids']: idmap.update({'ctx': rctx['ids']['ctx']}) try: for prule in crule.properties.values(): value = prule.co_value if type(value) is CodeType: value = eval(value, idmap) ctx[prule.name] = value for prule in crule.handlers: value = eval(prule.value, idmap) ctx[prule.name] = value except Exception as e: tb = sys.exc_info()[2] raise BuilderException(prule.ctx, prule.line, '{}: {}'.format( e.__class__.__name__, e), cause=tb) # create the template with an explicit ctx child = cls(**ctx) widget.add_widget(child) # reference it on our root rule context if crule.id: rctx['ids'][crule.id] = child else: # we got a "normal" rule, construct it manually # we can't construct it without __no_builder=True, because the # previous implementation was doing the add_widget() before # apply(), and so, we could use "self.parent". child = cls(__no_builder=True) widget.add_widget(child) self.apply(child) self._apply_rule(child, crule, rootrule) # append the properties and handlers to our final resolution task if rule.properties: rctx['set'].append( (widget.proxy_ref, list(rule.properties.values()))) for key, crule in rule.properties.items(): # clear previously applied rules if asked if crule.ignore_prev: Builder.unbind_property(widget, key) if rule.handlers: rctx['hdl'].append((widget.proxy_ref, rule.handlers)) # if we are applying another rule that the root one, then it's done for # us! if rootrule is not rule: del self.rulectx[rule] return # normally, we can apply a list of properties with a proper context try: rule = None for widget_set, rules in reversed(rctx['set']): for rule in rules: assert (isinstance(rule, ParserRuleProperty)) key = rule.name value = rule.co_value if type(value) is CodeType: value, bound = create_handler(widget_set, widget_set, key, value, rule, rctx['ids']) # if there's a rule if (widget_set != widget or bound or key not in ignored_consts): setattr(widget_set, key, value) else: if (widget_set != widget or key not in ignored_consts): setattr(widget_set, key, value) except Exception as e: if rule is not None: tb = sys.exc_info()[2] raise BuilderException(rule.ctx, rule.line, '{}: {}'.format(e.__class__.__name__, e), cause=tb) raise e # build handlers try: crule = None for widget_set, rules in rctx['hdl']: for crule in rules: assert (isinstance(crule, ParserRuleProperty)) assert (crule.name.startswith('on_')) key = crule.name if not widget_set.is_event_type(key): key = key[3:] idmap = copy(global_idmap) idmap.update(rctx['ids']) idmap['self'] = widget_set.proxy_ref if not widget_set.fbind(key, custom_callback, crule, idmap): raise AttributeError(key) #hack for on_parent if crule.name == 'on_parent': Factory.Widget.parent.dispatch(widget_set.__self__) except Exception as e: if crule is not None: tb = sys.exc_info()[2] raise BuilderException(crule.ctx, crule.line, '{}: {}'.format(e.__class__.__name__, e), cause=tb) raise e # rule finished, forget it del self.rulectx[rootrule]