def __init__(self, name=None, template=None, default=None, **params): """Widget initialization. All initialization has to take place in this method. It's not thread-safe to mutate widget's attributes outside this method or anytime after widget's first display. *Must* call super(MyWidget, self).__init__(*args, **kw) cooperatively, unless, of course, your know what you're doing. Preferably this should be done before any actual work is done in the method. Parameters: name : The widget's name. In input widgets, this will also be the name of the variable that the form will send to the controller. This is the only param that is safe to pass as a positional argument to __init__. template : The template that the widget should use to display itself. Currently only Kid templates are supported. You can both initialize with a template string or with the path to a file-base template: "myapp.templates.widget_tmpl" default : Default value to display when no value is passed at display time. **params : Keyword arguments specific to your widget or to any of it's bases. If listed at class attribute 'params' the will be bound automatically to the widget instance. Note: Do not confuse these parameters with parameters listed at "params". Some widgets accept parameters at the constructor which are not listed params, these parameter won't be passed to the template, be automatically called, etc.. """ self._declaration_counter = counter.next() if name: self.name = name if template: self.template_c, self.template = load_kid_template(template) if default is not None: self.default = default # logic for managing the params attribute for param in self.__class__.params: if param in params: # make sure we don't keep references to mutables setattr(self, param, copy_if_mutable(params.pop(param))) else: # make sure we don't alter mutable class attributes value, mutable = copy_if_mutable( getattr(self.__class__, param), True) if mutable: # re-set it only if mutable setattr(self, param, value) for unused in params.iterkeys(): warnings.warn('keyword argument "%s" is unused at %r instance' % ( unused, self.__class__.__name__))
def display(self, value=None, **params): """Display the widget in a Kid template. Returns an elementtree node instance. If you need serialized output in a string, call 'render' instead. Probably you will not need to override or extend if inhertiting from Widget. @params: value : The value to display in the widget. **params: Extra parameters specific to the widget. All keyword params supplied will pass through the update_params method which will have a last chance to modify them before reaching the template. """ if not getattr(self, 'template_c', False): warnings.warn("Widget instance '%r' has no template defined" % self) return None # logic for managing the params attribute for param in self.__class__.params: if param in params: param_value = params[param] if callable(param_value): param_value = param_value() else: # if the param hasn't been overridden (passed as a keyword # argument inside **params) put the corresponding instance # value inside params. param_value = getattr(self, param, None) # make sure we don't pass a reference to mutables params[param] = copy_if_mutable(param_value) if not params.get('name'): params['name'] = self.name if 'assume_encoding' not in params: params['assume_encoding'] = config.get('kid.assume_encoding', 'utf-8') params['value'] = to_unicode(self.adjust_value(value, **params)) self.update_params(params) # update_data has been deprecated self.update_data(params) try: transform = view.engines['kid'].transform except (KeyError, AttributeError): # this can happen if you render a widget before application startup # when view.load_engines() has not yet been called raise RuntimeError("Trying to render a widget," " but Kid templating engine is not yet loaded.") return transform(params, self.template_c)
def test_copy_if_mutable(): test_values = ((None, False), ('foo', False), (42, False), ((1, 2), False), ([1, 2], True), ({1: 2}, True)) for value, mutable in test_values: if mutable: assert util.copy_if_mutable(value) == value assert util.copy_if_mutable(value) is not value ret = util.copy_if_mutable(value, True) assert ret[0] == value assert ret[0] is not value assert ret[1] is True else: assert util.copy_if_mutable(value) is value ret = util.copy_if_mutable(value, True) assert ret[0] is value assert ret[1] is False
def test_copy_if_mutable(): test_values = ((None, False), ('foo', False), (42, False), ((1, 2), False), ([1, 2], True), ({ 1: 2 }, True)) for value, mutable in test_values: if mutable: assert util.copy_if_mutable(value) == value assert util.copy_if_mutable(value) is not value ret = util.copy_if_mutable(value, True) assert ret[0] == value assert ret[0] is not value assert ret[1] is True else: assert util.copy_if_mutable(value) is value ret = util.copy_if_mutable(value, True) assert ret[0] is value assert ret[1] is False
def display(self, value=None, **params): """ Display the widget in a Kid template. Returns an elementtree node instance. If you need serialized output in a string call 'render' instead. Probably you will not need to override or extend if inhertitting from Widget. @params: value : The value to display in the widget. **params : Extra parameters specific to the widget. All keyword params supplied will pass through the update_params method which will have a last chance to modify them before reaching the template. """ if not getattr(self, "template_c", False): warnings.warn("Widget instance '%r' has no template defined" % self) return None # logic for managing the params attribute for param in self.__class__.params: if param in params: param_value = params[param] if callable(param_value): param_value = param_value() else: # if the param hasn't been overridden (passed as a keyword # argument inside **params) put the corresponding instance # value inside params. param_value = getattr(self, param, None) # make sure we don't pass a reference to mutables params[param] = copy_if_mutable(param_value) params["name"] = self.name params["value"] = to_unicode(self.adjust_value(value, **params)) self.update_params(params) # update_data has been deprecated self.update_data(params) return view.engines.get("kid").transform(params, self.template_c)
def display(self, value=None, **params): """Display the widget in a Kid template. Returns an elementtree node instance. If you need serialized output in a string, call 'render' instead. Probably you will not need to override or extend if inheriting from Widget. @params: value : The value to display in the widget. **params: Extra parameters specific to the widget. All keyword params supplied will pass through the update_params method which will have a last chance to modify them before reaching the template. """ if not getattr(self, 'template_c', False): warnings.warn('kid' in view.engines and "Widget instance %r has no template defined" % self or "Trying to render a widget, but the Kid" " templating engine is not installed or not yet loaded.") return None # logic for managing the params attribute for param in self.__class__.params: if param in params: param_value = params[param] if callable(param_value): param_value = param_value() else: # if the param hasn't been overridden (passed as a keyword # argument inside **params) put the corresponding instance # value inside params. param_value = getattr(self, param, None) # make sure we don't pass a reference to mutables params[param] = copy_if_mutable(param_value) if not params.get('name'): params['name'] = self.name if value is None: value = self.default if callable(value): value = value() params['value'] = to_unicode(self.adjust_value(value, **params)) self.update_params(params) try: transform = view.engines['kid'].transform except (KeyError, AttributeError): # this can happen if you render a widget before application startup # when view.load_engines() has not yet been called raise RuntimeError("Trying to render a widget, but the Kid" " templating engine is not installed or not yet loaded.") # If the page template is Genshi, we keep track of the nesting level, # because Genshi cannot display Kid's ElementTree elements directly. if request_available() and request.tg_template_enginename == 'genshi': display_level = getattr(request, 'tg_widgets_display_level', 0) request.tg_widgets_display_level = display_level + 1 else: display_level = None try: output = transform(params, self.template_c) if display_level == 0: # On the topmost level, we create a Genshi markup stream # from Kid's ElementTree element to make Genshi really happy. # This automatism makes wrapping widget output with ET(...) # calls in Genshi page templates unnecessary. output = view.genshi_et(output) finally: if display_level is not None: request.tg_widgets_display_level = display_level return output
def __init__(self, name=None, template=None, default=None, **params): """Widget initialization. All initialization has to take place in this method. It's not thread-safe to mutate widget's attributes outside this method or anytime after widget's first display. *Must* call super(MyWidget, self).__init__(*args, **kw) cooperatively, unless, of course, your know what you're doing. Preferably this should be done before any actual work is done in the method. Parameters: name : The widget's name. In input widgets, this will also be the name of the variable that the form will send to the controller. This is the only param that is safe to pass as a positional argument to __init__. template : The template that the widget should use to display itself. Currently only Kid templates are supported. You can both initialize with a template string or with the path to a file-base template: "myapp.templates.widget_tmpl" default : Default value to display when no value is passed at display time. **params : Keyword arguments specific to your widget or to any of it's bases. If listed at class attribute 'params' the will be bound automatically to the widget instance. Note: Do not confuse these parameters with parameters listed at "params". Some widgets accept parameters at the constructor which are not listed params, these parameter won't be passed to the template, be automatically called, etc.. """ self._declaration_counter = counter.next() if name: self.name = name if template: self.template_c, self.template = load_kid_template(template) if default is not None: self.default = default # logic for managing the params attribute for param in self.__class__.params: if param in params: # make sure we don't keep references to mutables setattr(self, param, copy_if_mutable(params.pop(param))) else: if hasattr(self, param): # make sure we don't alter mutable class attributes value = copy_if_mutable(getattr(self.__class__, param), True) if value[1]: # re-set it only if mutable setattr(self, param, value[0]) else: setattr(self, param, None) for unused in params.iterkeys(): warnings.warn('keyword argument "%s" is unused at %r instance' % (unused, self.__class__.__name__))