Beispiel #1
0
    def _gen_header(self, ctx, cls, name, parent):
        logger.debug("Generate header for %r", cls)

        with parent.element('thead'):
            with parent.element('tr'):
                th_attrs = {}
                if self.field_name_attr is not None:
                    th_attrs[self.field_name_attr] = name

                if issubclass(cls, ComplexModelBase):
                    fti = cls.get_flat_type_info(cls)
                    if self.field_name_attr is None:
                        for k, v in fti.items():
                            attr = get_cls_attrs(self, v)
                            if attr.exc:
                                continue
                            header_name = self.trc(v, ctx.locale, k)
                            parent.write(E.th(header_name, **th_attrs))
                    else:
                        for k, v in fti.items():
                            attr = get_cls_attrs(self, v)
                            if attr.exc:
                                continue
                            th_attrs[self.field_name_attr] = k
                            header_name = self.trc(v, ctx.locale, k)
                            parent.write(E.th(header_name, **th_attrs))

                else:
                    if self.field_name_attr is not None:
                        th_attrs[self.field_name_attr] = name
                    header_name = self.trc(cls, ctx.locale, name)
                    parent.write(E.th(header_name, **th_attrs))

                self.extend_header_row(ctx, cls, name, parent)
Beispiel #2
0
    def _gen_header(self, ctx, cls, name, parent):
        logger.debug("Generate header for %r", cls)

        with parent.element('thead'):
            with parent.element('tr'):
                th_attrs = {}
                if self.field_name_attr is not None:
                    th_attrs[self.field_name_attr] = name

                if issubclass(cls, ComplexModelBase):
                    fti = cls.get_flat_type_info(cls)
                    if self.field_name_attr is None:
                        for k, v in fti.items():
                            attr = get_cls_attrs(self, v)
                            if attr.exc:
                                continue
                            header_name = self.trc(v, ctx.locale, k)
                            parent.write(E.th(header_name, **th_attrs))
                    else:
                        for k, v in fti.items():
                            attr = get_cls_attrs(self, v)
                            if attr.exc:
                                continue
                            th_attrs[self.field_name_attr] = k
                            header_name = self.trc(v, ctx.locale, k)
                            parent.write(E.th(header_name, **th_attrs))

                else:
                    if self.field_name_attr is not None:
                        th_attrs[self.field_name_attr] = name
                    header_name = self.trc(cls, ctx.locale, name)
                    parent.write(E.th(header_name, **th_attrs))

                self.extend_header_row(ctx, cls, parent, name)
Beispiel #3
0
    def datetime_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
        ctx.protocol.assets.extend([('jquery',), ('jquery-ui', 'datepicker'),
                                                        ('jquery-timepicker',)])

        cls_attrs = get_cls_attrs(self, cls)
        elt = self._gen_input(cls, None, name, cls_attrs)
        elt.attrib['type'] = 'text'

        if cls_attrs.format is None:
            data_format = 'yy-mm-dd HH:MM:SS'

        else:
            data_format = cls_attrs.format.replace('%Y', 'yy') \
                                          .replace('%m', 'mm') \
                                          .replace('%d', 'dd') \
                                          .replace('%H', 'HH') \
                                          .replace('%M', 'MM') \
                                          .replace('%S', 'SS')

        code = [
            "$('#%(field_name)s').datetimepicker();",
            "$('#%(field_name)s').datetimepicker('option', 'DateTimeFormat', '%(format)s');",
        ]

        if inst is None:
            script = _format_js(code, field_name=elt.attrib['id'],
                                                             format=data_format)
        else:
            value = self.to_string(cls, inst)
            code.append("$('#%(field_name)s').datetimepicker('setDate', '%(value)s');")
            script = _format_js(code, field_name=elt.attrib['id'],
                                                format=data_format, value=value)

        parent.write(_idiv(self._gen_label(ctx, cls, name, elt), elt, script))
Beispiel #4
0
    def _pull_to_parent(self, ctx, cls, inst, parent, name, parent_inst=None,
                        label_attrs=None, parent_key=None, no_label=False,
                        **kwargs):
        key = self.selsafe(name)
        attr = get_cls_attrs(self, cls)

        if inst is None:
            inst = []

        for i, subval in enumerate(inst):
            new_key = '%s[%09d]' % (key, i)
            with parent.element('div', {"class": key}):
                ret = self.to_parent(ctx, cls, subval, parent, new_key,
                                parent_inst=parent_inst, no_label=True,
                                from_arr=True, **kwargs)
                if not attr.no_write:
                    parent.write(E.button('+', **{
                                  "class": key + "_btn_add", 'type': 'button'}))
                    parent.write(E.button('-', **{
                                  "class": key + "_btn_del", 'type': 'button'}))

                if isgenerator(ret):
                    try:
                        while True:
                            sv2 = (yield)
                            ret.send(sv2)
                    except Break as b:
                        try:
                            ret.throw(b)
                        except StopIteration:
                            pass

        if not attr.no_write:
            _gen_array_js(parent, key)
Beispiel #5
0
    def _get_member_pairs(self, cls, inst):
        parent_cls = getattr(cls, '__extends__', None)
        if parent_cls is not None:
            for r in self._get_member_pairs(parent_cls, inst):
                yield r

        for k, v in cls._type_info.items():
            attr = get_cls_attrs(self, v)

            if getattr(attr, 'exc', None):
                continue

            try:
                subinst = getattr(inst, k, None)
            # to guard against e.g. sqlalchemy throwing NoSuchColumnError
            except Exception as e:
                logger.error("Error getting %r: %r" %(k,e))
                subinst = None

            if subinst is None:
                subinst = v.Attributes.default

            val = self._object_to_doc(v, subinst)
            min_o = v.Attributes.min_occurs

            if val is not None or min_o > 0 or self.complex_as is list:
                sub_name = v.Attributes.sub_name
                if sub_name is None:
                    sub_name = k

                yield (sub_name, val)
Beispiel #6
0
    def integer_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
        cls_attrs = get_cls_attrs(self, cls)
        elt = self._gen_input(cls, inst, name, cls_attrs)
        elt.attrib['type'] = 'number'

        self._apply_number_constraints(cls_attrs, elt)

        parent.write(_idiv(self._gen_label(ctx, cls, name, elt), elt))
Beispiel #7
0
 def _form_key(sort_key):
     k, v = sort_key
     attrs = get_cls_attrs(prot, v)
     return None if attrs.tab is None else \
                             (attrs.tab.index, attrs.tab.htmlid), \
            None if attrs.fieldset is None else \
                             (attrs.fieldset.index, attrs.fieldset.htmlid), \
            attrs.order, k
Beispiel #8
0
    def boolean_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
        cls_attrs = get_cls_attrs(self, cls)
        elt = self._gen_input(cls, inst, name, cls_attrs)
        elt.attrib.update({'type': 'checkbox', 'value': 'true'})

        if bool(inst):
            elt.attrib['checked'] = ''

        parent.write(_idiv(elt, self._gen_label(ctx, cls, name, elt)))
Beispiel #9
0
    def _write_members(self, ctx, cls, inst, parent):
        parent_cls = getattr(cls, '__extends__', None)

        if not (parent_cls is None):
            ret = self._write_members(ctx, parent_cls, inst, parent)
            if ret is not None:
                try:
                    while True:
                        sv2 = (yield)
                        ret.send(sv2)

                except Break:
                    try:
                        ret.throw(Break())
                    except StopIteration:
                        pass

        for k, v in cls._type_info.items():
            attr = get_cls_attrs(self, v)
            if attr.exc:
                continue

            try:  # e.g. SqlAlchemy could throw NoSuchColumnError
                subvalue = getattr(inst, k, None)
            except:
                subvalue = None

            # This is a tight loop, so enable this only when necessary.
            # logger.debug("get %r(%r) from %r: %r" % (k, v, inst, subvalue))

            if issubclass(v, XmlData):
                if subvalue is not None:
                    parent.write(self.to_unicode(k.type, subvalue))
                continue

            sub_ns = v.Attributes.sub_ns
            if sub_ns is None:
                sub_ns = cls.get_namespace()

            sub_name = v.Attributes.sub_name
            if sub_name is None:
                sub_name = k

            name = "{%s}%s" % (sub_ns, sub_name)
            if subvalue is not None or v.Attributes.min_occurs > 0:
                ret = self.to_parent(ctx, v, subvalue, parent, name)
                if ret is not None:
                    try:
                        while True:
                            sv2 = (yield)
                            ret.send(sv2)
                    except Break as b:
                        try:
                            ret.throw(b)
                        except StopIteration:
                            pass
Beispiel #10
0
    def _gen_input_unicode(self, cls, inst, name, **_):
        cls_attrs = get_cls_attrs(self, cls)

        elt = self._gen_input(cls, inst, name, cls_attrs)
        elt.attrib['type'] = 'text'

        if cls_attrs.max_len < Unicode.Attributes.max_len:
            elt.attrib['maxlength'] = str(int(cls_attrs.max_len))
        if cls_attrs.min_len > Unicode.Attributes.min_len:
            elt.attrib['minlength'] = str(int(cls_attrs.min_len))

        return cls_attrs, elt
Beispiel #11
0
    def decimal_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
        cls_attrs = get_cls_attrs(self, cls)
        elt = self._gen_input(cls, inst, name, cls_attrs)
        elt.attrib['type'] = 'number'

        if D(cls.Attributes.fraction_digits).is_infinite():
            elt.attrib['step'] = 'any'
        else:
            elt.attrib['step'] = str(10**(-int(cls.Attributes.fraction_digits)))

        self._apply_number_constraints(cls_attrs, elt)

        parent.write(_idiv(self._gen_label(ctx, cls, name, elt), elt))
Beispiel #12
0
def spyne_to_argparse(cls):
    fti = cls.get_flat_type_info(cls)
    parser = ArgumentParser(description=cls.__doc__)

    parser.add_argument('-c',
                        '--config-file',
                        type=os.path.abspath,
                        help="An alternative config file.")

    for k, v in sorted(fti.items(), key=lambda i: i[0]):
        attrs = get_cls_attrs(None, v)
        if attrs.no_cli:
            continue

        args = ['--%s' % k.replace('_', '-')]
        if attrs.short is not None:
            args.append('-%s' % attrs.short)

        assert not ('-c' in args or '--config-file' in args)

        kwargs = {}

        if attrs.help is not None:
            kwargs['help'] = attrs.help

        # types
        if _is_array_of_primitives(v):
            kwargs['nargs'] = "+"

        elif _is_array_of_complexes(v):
            continue

        elif issubclass(v, Boolean):
            kwargs['action'] = "store_const"
            kwargs['const'] = True

        elif issubclass(v, Unicode):
            if len(v.Attributes.values) > 0:
                kwargs['type'] = enum(v.Attributes.values)
            else:
                kwargs['type'] = six.text_type

        elif issubclass(v, tuple(ARGTYPE_MAP.keys())):
            kwargs['type'] = ARGTYPE_MAP[v]

        parser.add_argument(*args, **kwargs)

    return parser
Beispiel #13
0
    def _gen_tab_headers(self, ctx, fti):
        retval = E.ul()

        tabs = {}
        for k, v in fti.items():
            subattr = get_cls_attrs(self, v)
            tab = subattr.tab
            if tab is not None:
                tabs[id(tab)] = tab

        for i, tab in enumerate(sorted(tabs.values(),
                                            key=lambda t: (t.index, t.htmlid))):
            retval.append(E.li(E.a(
                self.trd(tab.legend, ctx.locale, "Tab %d" % i),
                href="#" + tab.htmlid
            )))

        return retval
Beispiel #14
0
    def _gen_row(self, ctx, cls, inst, parent, name, **kwargs):
        print("Generate row for", cls)
        with parent.element('tr'):
            for k, v in cls.get_flat_type_info(cls).items():
                attr = get_cls_attrs(self, v)
                if attr.exc:
                    print("\tExclude field %r type %r" % (k, v), "for", cls)
                    continue
                if not attr.get('read', True):
                    continue

                print("\tGenerate field %r type %r" % (k, v), "for", cls)

                try:
                    sub_value = getattr(inst, k, None)
                except: # to guard against e.g. SQLAlchemy throwing NoSuchColumnError
                    sub_value = None

                sub_name = attr.sub_name
                if sub_name is None:
                    sub_name = k

                td_attrs = {}
                if self.field_name_attr is not None:
                    td_attrs[self.field_name_attr] = sub_name

                with parent.element('td', td_attrs):
                    ret = self.to_parent(ctx, v, sub_value, parent, sub_name,
                                                                       **kwargs)

                    if isgenerator(ret):
                        try:
                            while True:
                                sv2 = (yield)
                                ret.send(sv2)
                        except Break as b:
                            try:
                                ret.throw(b)
                            except StopIteration:
                                pass

            print("Generate row for %r done." % cls)
            self.extend_data_row(ctx, cls, inst, parent, name, **kwargs)
Beispiel #15
0
    def _gen_row(self, ctx, cls, inst, parent, name, **kwargs):
        print("Generate row for", cls)
        with parent.element('tr'):
            for k, v in cls.get_flat_type_info(cls).items():
                attr = get_cls_attrs(self, v)
                if attr.exc:
                    print("\tExclude field %r type %r" % (k, v), "for", cls)
                    continue
                if not attr.get('read', True):
                    continue

                print("\tGenerate field %r type %r" % (k, v), "for", cls)

                try:
                    sub_value = getattr(inst, k, None)
                except: # to guard against e.g. SQLAlchemy throwing NoSuchColumnError
                    sub_value = None

                sub_name = attr.sub_name
                if sub_name is None:
                    sub_name = k

                td_attrs = {}
                if self.field_name_attr is not None:
                    td_attrs[self.field_name_attr] = sub_name

                with parent.element('td', td_attrs):
                    ret = self.to_parent(ctx, v, sub_value, parent, sub_name,
                                                                       **kwargs)

                    if isgenerator(ret):
                        try:
                            while True:
                                sv2 = (yield)
                                ret.send(sv2)
                        except Break as b:
                            try:
                                ret.throw(b)
                            except StopIteration:
                                pass

            print("Generate row for %r done." % cls)
            self.extend_data_row(ctx, cls, inst, parent, name, **kwargs)
Beispiel #16
0
def _apply_custom_attributes(cls):
    fti = cls.get_flat_type_info(cls)
    for k, v in sorted(fti.items(), key=lambda i: i[0]):
        attrs = get_cls_attrs(None, v)
        if attrs.no_config == True:
            v.Attributes.prot_attrs = {YamlDocument: dict(exc=True)}
Beispiel #17
0
    def complex_model_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
        global SOME_COUNTER

        fti = cls.get_flat_type_info(cls)
        prev_fset = fset_ctx = None
        prev_tab = tab_ctx = tabview_ctx = None
        tabview_id = None

        # FIXME: hack! why do we have top-level object receiving name?
        if name == cls.get_type_name():
            name = ''

        with parent.element('fieldset'):
            parent.write(E.legend(cls.get_type_name()))
            for k, v in sorted(fti.items(), key=_Tform_key(self)):
                subattr = get_cls_attrs(self, v)
                if subattr.exc:
                    continue

                subinst = getattr(inst, k, None)

                tab = subattr.tab
                print("TAB", k, getattr(v.Attributes, 'tab', None), subattr.tab)
                if not (tab is prev_tab):
                    if fset_ctx is not None:
                        fset_ctx.__exit__(None, None, None)
                        print("exiting fset tab ", prev_fset)

                    fset_ctx = prev_fset = None

                    if tab_ctx is not None:
                        tab_ctx.__exit__(None, None, None)
                        print("exiting tab", prev_tab)

                    if prev_tab is None:
                        print("entering tabview")
                        tabview_id = 'tabview' + str(SOME_COUNTER)
                        SOME_COUNTER += 1

                        tabview_ctx = parent.element('div', attrib={'id': tabview_id})
                        tabview_ctx.__enter__()

                        parent.write(self._gen_tab_headers(ctx, fti))

                    print("entering tab", tab)

                    attrib = {'id': tab.htmlid}
                    attrib.update(tab.attrib)
                    tab_ctx = parent.element('div', attrib)
                    tab_ctx.__enter__()

                    prev_tab = tab

                fset = subattr.fieldset
                if not (fset is prev_fset):
                    if fset_ctx is not None:
                        fset_ctx.__exit__(None, None, None)
                        print("exiting fset norm", prev_fset)

                    print("entering fset", fset)
                    fset_ctx = parent.element(fset.tag, fset.attrib)
                    fset_ctx.__enter__()

                    parent.write(E.legend(self.trd(fset.legend, ctx.locale, k)))
                    prev_fset = fset

                if name is not None and len(name) > 0:
                    child_key = self.hier_delim.join((name, k))
                else:
                    child_key = k

                ret = self.to_parent(ctx, v, subinst, parent, child_key, **kwargs)
                if isgenerator(ret):
                    try:
                        while True:
                            y = (yield)
                            ret.send(y)

                    except Break as b:
                        try:
                            ret.throw(b)
                        except StopIteration:
                            pass

            if fset_ctx is not None:
                fset_ctx.__exit__(None, None, None)
                print("exiting fset close", fset)

            if tab_ctx is not None:
                tab_ctx.__exit__(None, None, None)
                print("exiting tab close", fset)

            if tabview_ctx is not None:
                tabview_ctx.__exit__(None, None, None)
                parent.write(E.script(
                    '$(function() { $( "#%s" ).tabs();});' % tabview_id,
                    type="text/javascript"
                ))

                print("exiting tabview close", fset)
Beispiel #18
0
    def duration_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
        cls_attrs = get_cls_attrs(self, cls)
        elt = self._gen_input(cls, inst, name, cls_attrs)

        parent.write(_idiv(self._gen_label(ctx, cls, name, elt), elt))
Beispiel #19
0
    def _gen_row(self,
                 ctx,
                 cls,
                 inst,
                 parent,
                 name,
                 from_arr=False,
                 array_index=None,
                 **kwargs):

        # because HtmlForm* protocols don't use the global null handler, it's
        # possible for null values to reach here.
        if inst is None:
            return

        print("Generate row for", cls)

        with parent.element('tr'):
            for k, v in cls.get_flat_type_info(cls).items():
                attr = get_cls_attrs(self, v)
                if attr.exc:
                    print("\tExclude table cell %r type %r" % (k, v), "for",
                          cls)
                    continue
                if not attr.get('read', True):
                    continue

                print("\tGenerate table cell %r type %r" % (k, v), "for", cls)

                try:
                    sub_value = getattr(inst, k, None)
                except:  # e.g. SQLAlchemy could throw NoSuchColumnError
                    sub_value = None

                sub_name = attr.sub_name
                if sub_name is None:
                    sub_name = k
                if self.hier_delim is not None:
                    if array_index is None:
                        sub_name = "%s%s%s" % (name, self.hier_delim, sub_name)
                    else:
                        sub_name = "%s[%d]%s%s" % (name, array_index,
                                                   self.hier_delim, sub_name)

                td_attrs = {}
                if self.field_name_attr is not None:
                    td_attrs[self.field_name_attr] = attr.sub_name or k

                with parent.element('td', td_attrs):
                    if attr.href is not None:
                        try:
                            attrib = {'href': attr.href % sub_value}
                        except:
                            attrib = {'href': attr.href}

                        with parent.element('a', attrib=attrib):
                            ret = self.to_parent(ctx,
                                                 v,
                                                 sub_value,
                                                 parent,
                                                 sub_name,
                                                 from_arr=from_arr,
                                                 array_index=array_index,
                                                 **kwargs)
                    else:
                        ret = self.to_parent(ctx,
                                             v,
                                             sub_value,
                                             parent,
                                             sub_name,
                                             from_arr=from_arr,
                                             array_index=array_index,
                                             **kwargs)

                    if isgenerator(ret):
                        try:
                            while True:
                                sv2 = (yield)
                                ret.send(sv2)
                        except Break as b:
                            try:
                                ret.throw(b)
                            except StopIteration:
                                pass

            m = cls.Attributes.methods
            if m is not None and len(m) > 0:
                with parent.element('td'):
                    first = True
                    mrpc_delim = html.fromstring("&nbsp;|&nbsp;").text

                    for mn, md in self._methods(cls, inst):
                        if first:
                            first = False
                        else:
                            parent.write(mrpc_delim)

                        pd = {}
                        for k, v in cls.get_flat_type_info(cls).items():
                            if getattr(v.Attributes, 'primary_key', None):
                                r = self.to_unicode(v, getattr(inst, k, None))
                                if r is not None:
                                    pd[k] = r

                        params = urlencode(pd)

                        mdid2key = ctx.app.interface.method_descriptor_id_to_key
                        href = mdid2key[id(md)].rsplit("}", 1)[-1]
                        text = md.translate(ctx.locale,
                                            md.in_message.get_type_name())
                        parent.write(E.a(text, href="%s?%s" % (href, params)))

            print("Generate row for %r done." % cls)
            self.extend_data_row(ctx,
                                 cls,
                                 inst,
                                 parent,
                                 name,
                                 array_index=array_index,
                                 **kwargs)
Beispiel #20
0
    def _doc_to_object(self, cls, doc, validator=None):
        if doc is None:
            return []

        if issubclass(cls, Array):
            retval = []
            (serializer, ) = cls._type_info.values()

            for i, child in enumerate(doc):
                retval.append(
                    self._from_dict_value(i, serializer, child, validator))

            return retval

        if not self.ignore_wrappers:
            if not isinstance(doc, dict):
                raise ValidationError("Wrapper documents must be dicts")
            if len(doc) == 0:
                return None
            if len(doc) > 1:
                raise ValidationError(
                    doc, "There can be only one entry in a "
                    "wrapper dict")

            subclasses = cls.get_subclasses()
            (class_name, doc), = doc.items()
            if cls.get_type_name() != class_name and subclasses is not None \
                                                        and len(subclasses) > 0:
                for subcls in subclasses:
                    if subcls.get_type_name() == class_name:
                        break

                if not self.issubclass(subcls, cls):
                    raise ValidationError(
                        class_name, "Class name %%r is not a subclass of %r" %
                        cls.get_type_name())
                cls = subcls

        inst = cls.get_deserialization_instance()

        # get all class attributes, including the ones coming from parent classes.
        flat_type_info = cls.get_flat_type_info(cls)

        # this is for validating cls.Attributes.{min,max}_occurs
        frequencies = defaultdict(int)

        try:
            items = doc.items()
        except AttributeError:
            # Input is not a dict, so we assume it's a sequence that we can pair
            # with the incoming sequence with field names.
            # TODO: cache this
            items = zip([
                k for k, v in flat_type_info.items()
                if not get_cls_attrs(self, v).exc
            ], doc)

        # parse input to set incoming data to related attributes.
        for k, v in items:
            member = flat_type_info.get(k, None)
            if member is None:
                member, k = flat_type_info.alt.get(k, (None, k))
                if member is None:
                    continue

            attr = get_cls_attrs(self, member)

            mo = attr.max_occurs
            if mo > 1:
                subinst = getattr(inst, k, None)
                if subinst is None:
                    subinst = []

                for a in v:
                    subinst.append(
                        self._from_dict_value(k, member, a, validator))

            else:
                subinst = self._from_dict_value(k, member, v, validator)

            inst._safe_set(k, subinst, member)

            frequencies[k] += 1

        if validator is self.SOFT_VALIDATION and cls.Attributes.validate_freq:
            _check_freq_dict(cls, frequencies, flat_type_info)

        return inst