def reorder_type_info(fields, type_info, allow_partial=False):
    """
    re-order the given type_info into the order given with fields. Anything
    not mentioned in fields, will be appended last.
    """

    copy = TypeInfo(type_info.items())
    new = TypeInfo()
    for field in fields:
        if field not in copy:
            if allow_partial:
                # If we order the <gelijk> element, this element can contain far less elements than the <object>
                # element. This is a workaround by assuming the gelijk-order it the same as the object-order.
                continue
            else:
                raise KeyError('All fields must be present in the Spyne model: {} is missing.'.format(field))

        value = copy[field]
        del copy[field]
        new[field] = value

    # Add the fields not specified in fields last.
    for field, value in copy.items():
        new[field] = value
    return new
Exemple #2
0
def _produce_input_message(f, params, kparams, _in_message_name,
                           _in_variable_names, no_ctx, no_self, args):
    _body_style = _validate_body_style(kparams)

    arg_start = 0
    if no_ctx is False:
        arg_start += 1
    if no_self is False:
        arg_start += 1

    if args is None:
        try:
            argcount = f.__code__.co_argcount
            args = f.__code__.co_varnames[arg_start:argcount]

        except AttributeError:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts."
            )

        if len(params) != len(args):
            raise Exception("%r function has %d argument(s) but its decorator "
                            "has %d." % (f.__name__, len(args), len(params)))

    else:
        args = copy(args)
        if len(params) != len(args):
            raise Exception("%r function has %d argument(s) but the _args "
                            "argument has %d." % (f.__name__, len(args), len(params)))

    in_params = TypeInfo()
    for k, v in zip(args, params):
        k = _in_variable_names.get(k, k)
        in_params[k] = v

    ns = spyne.const.xml_ns.DEFAULT_NS
    if _in_message_name.startswith("{"):
        ns, _, _in_message_name = _in_message_name[1:].partition("}")

    if _body_style == 'bare':
        if len(in_params) > 1:
            raise Exception("body_style='bare' can handle at most one function "
                            "argument.")
        if len(in_params) == 0:
            message = ComplexModel.produce(type_name=_in_message_name,
                                           namespace=ns, members=in_params)
        else:
            message, = in_params.values()
            message = message.customize(sub_name=_in_message_name, sub_ns=ns)
            assert message.Attributes.sub_name is not None

    else:
        message = ComplexModel.produce(type_name=_in_message_name,
                                       namespace=ns, members=in_params)
        message.__namespace__ = ns

    return message
Exemple #3
0
def reorder_type_info(fields, type_info, allow_partial=False):
    """
    re-order the given type_info into the order given with fields. Anything
    not mentioned in fields, will be appended last.
    """

    copy = TypeInfo(type_info.items())
    new = TypeInfo()
    for field in fields:
        if field not in copy:
            if allow_partial:
                # If we order the <gelijk> element, this element can contain far less elements than the <object>
                # element. This is a workaround by assuming the gelijk-order it the same as the object-order.
                continue
            else:
                raise KeyError(
                    'All fields must be present in the Spyne model: {} is missing.'
                    .format(field))

        value = copy[field]
        del copy[field]
        new[field] = value

    # Add the fields not specified in fields last.
    for field, value in copy.items():
        new[field] = value
    return new
Exemple #4
0
def _produce_output_message(func_name, kparams):
    """Generate an output message for "rpc"-style API methods.

    This message is a wrapper to the declared return type.
    """

    _returns = kparams.get('_returns')
    _body_style = _validate_body_style(kparams)

    # FIXME: Remove after detecting all broken code
    _out_body_bare = kparams.get("_out_body_bare", 0xcc)
    assert _out_body_bare == 0xcc

    _out_message_name = kparams.get(
        '_out_message_name', '%s%s' % (func_name, spyne.const.RESPONSE_SUFFIX))

    out_params = TypeInfo()

    if _returns and _body_style == 'wrapped':
        if isinstance(_returns, (list, tuple)):
            default_names = [
                '%s%s%d' % (func_name, spyne.const.RESULT_SUFFIX, i)
                for i in range(len(_returns))
            ]

            _out_variable_names = kparams.get('_out_variable_names',
                                              default_names)

            assert (len(_returns) == len(_out_variable_names))

            var_pair = zip(_out_variable_names, _returns)
            out_params = TypeInfo(var_pair)

        else:
            _out_variable_name = kparams.get(
                '_out_variable_name',
                '%s%s' % (func_name, spyne.const.RESULT_SUFFIX))

            out_params[_out_variable_name] = _returns

    ns = spyne.const.xml_ns.DEFAULT_NS
    if _out_message_name.startswith("{"):
        ns = _out_message_name[1:].partition("}")[0]

    if _body_style.endswith('bare') and _returns is not None:
        message = _returns.customize(sub_name=_out_message_name, sub_ns=ns)
        if message.__type_name__ is ModelBase.Empty:
            message.__type_name__ = _out_message_name

    else:
        message = ComplexModel.produce(type_name=_out_message_name,
                                       namespace=ns,
                                       members=out_params)

        message.Attributes._wrapper = True
        message.__namespace__ = ns  # FIXME: is this necessary?

    return message
Exemple #5
0
    def test_insert(self):
        d = TypeInfo()

        d['a'] = 1
        assert d[0] == d['a'] == 1

        d.insert(0, ('b', 2))

        assert d[1] == d['a'] == 1
        assert d[0] == d['b'] == 2
Exemple #6
0
    def test_insert(self):
        d = TypeInfo()

        d['a'] = 1
        assert d[0] == d['a'] == 1

        d.insert(0, ('b', 2))

        assert d[1] == d['a'] == 1
        assert d[0] == d['b'] == 2
Exemple #7
0
    def test_insert_existing(self):
        d = TypeInfo()

        d["a"] = 1
        d["b"] = 2
        assert d[1] == d['b'] == 2

        d.insert(0, ('b', 3))
        assert d[1] == d['a'] == 1
        assert d[0] == d['b'] == 3
Exemple #8
0
    def test_insert_existing(self):
        d = TypeInfo()

        d["a"] = 1
        d["b"] = 2
        assert d[1] == d['b'] == 2

        d.insert(0, ('b', 3))
        assert d[1] == d['a'] == 1
        assert d[0] == d['b'] == 3
    def create_gelijk_model(self, stuf_entiteit=None):
        # TODO [TECH]: The gelijk model is required, and should always be set.
        stuf_entiteit = stuf_entiteit or self.stuf_entiteit
        type_info = TypeInfo()
        for related_field in stuf_entiteit.get_related_fields():
            try:
                # This is not consistent with the prototype-XSD. See Taiga issue #88
                type_info[related_field.field_name] = self.create_gelijk_model(related_field.stuf_entiteit)
            except EmptyResultError:
                pass

        # Create spyne model for 'gerelateerde'
        # TODO [TECH]: In the WSDL this should be minOccurs and maxOccurs of 1.
        gerelateerde = stuf_entiteit.get_gerelateerde()
        if gerelateerde:
            _, gerelateerde_data = gerelateerde
            if isinstance(gerelateerde_data, tuple) or isinstance(gerelateerde_data, list):
                for relation_name, related_cls in gerelateerde_data:
                    try:
                        sub_type_info = []
                        for relation_name, related_cls in gerelateerde_data:
                            sub_type_info.append((relation_name, self.create_gelijk_model(related_cls).customize(xml_choice_group='gerelateerde')))
                        sub_model = self.create_reusable_model(self.create_gelijk_name(stuf_entiteit, 'gerelateerde'), stuf_entiteit.get_namespace(), sub_type_info)
                        type_info['gerelateerde'] = sub_model
                    except EmptyResultError:
                        pass
            else:
                related_cls = gerelateerde_data
                try:
                    type_info.append(('gerelateerde', self.create_gelijk_model(related_cls)))
                except EmptyResultError:
                    pass

        field_mapping = stuf_entiteit.get_django_field_mapping(filter_fields=True)
        if not field_mapping and not type_info:
            raise EmptyResultError()

        # Build the Spyne model
        for field_name, django_field_name, django_field in field_mapping:
            type_info[field_name] = django_field_to_spyne_model(django_field)
        complex_model = self.create_reusable_model(
            self.create_gelijk_name(stuf_entiteit), stuf_entiteit.get_namespace(), type_info)

        if stuf_entiteit.is_entiteit():
            complex_model._type_info['entiteittype'] = XmlAttribute(simple_types.Entiteittype, ref='entiteittype', ns=STUF_XML_NS)
        complex_model._type_info.update(type_info)
        complex_model.stuf_entiteit = stuf_entiteit

        complex_model._type_info = reorder_type_info(stuf_entiteit.get_fields(), complex_model._type_info, allow_partial=True)

        return complex_model
    def create_gelijk_model(self, stuf_entiteit=None):
        # TODO [TECH]: The gelijk model is required, and should always be set.
        stuf_entiteit = stuf_entiteit or self.stuf_entiteit
        type_info = TypeInfo()
        for related_field in stuf_entiteit.get_related_fields():
            try:
                # This is not consistent with the prototype-XSD. See Taiga issue #88
                type_info[related_field.field_name] = self.create_gelijk_model(related_field.stuf_entiteit)
            except EmptyResultError:
                pass

        # Create spyne model for 'gerelateerde'
        # TODO [TECH]: In the WSDL this should be minOccurs and maxOccurs of 1.
        gerelateerde = stuf_entiteit.get_gerelateerde()
        if gerelateerde:
            _, gerelateerde_data = gerelateerde
            if isinstance(gerelateerde_data, tuple) or isinstance(gerelateerde_data, list):
                for relation_name, related_cls in gerelateerde_data:
                    try:
                        sub_type_info = []
                        for relation_name, related_cls in gerelateerde_data:
                            sub_type_info.append((relation_name, self.create_gelijk_model(related_cls).customize(xml_choice_group='gerelateerde')))
                        sub_model = self.create_reusable_model(self.create_gelijk_name(stuf_entiteit, 'gerelateerde'), stuf_entiteit.get_namespace(), sub_type_info)
                        type_info['gerelateerde'] = sub_model
                    except EmptyResultError:
                        pass
            else:
                related_cls = gerelateerde_data
                try:
                    type_info.append(('gerelateerde', self.create_gelijk_model(related_cls)))
                except EmptyResultError:
                    pass

        field_mapping = stuf_entiteit.get_django_field_mapping(filter_fields=True)
        if not field_mapping and not type_info:
            raise EmptyResultError()

        # Build the Spyne model
        for field_name, django_field_name, django_field in field_mapping:
            type_info[field_name] = django_field_to_spyne_model(django_field)
        complex_model = self.create_reusable_model(
            self.create_gelijk_name(stuf_entiteit), stuf_entiteit.get_namespace(), type_info)

        if stuf_entiteit.is_entiteit():
            complex_model._type_info['entiteittype'] = XmlAttribute(simple_types.Entiteittype, ref='entiteittype', ns=STUF_XML_NS)
        complex_model._type_info.update(type_info)
        complex_model.stuf_entiteit = stuf_entiteit

        complex_model._type_info = reorder_type_info(stuf_entiteit.get_fields(), complex_model._type_info, allow_partial=True)

        return complex_model
Exemple #11
0
def _produce_output_message(func_name, kparams):
    """Generate an output message for "rpc"-style API methods.

    This message is a wrapper to the declared return type.
    """

    _returns = kparams.get('_returns')
    _body_style = _validate_body_style(kparams)

    _out_message_name = kparams.get('_out_message',
                                    '%s%s' % (func_name, RESPONSE_SUFFIX))
    out_params = TypeInfo()

    if _returns and _body_style == 'wrapped':
        if isinstance(_returns, (list, tuple)):
            default_names = [
                '%s%s%d' % (func_name, RESULT_SUFFIX, i)
                for i in range(len(_returns))
            ]

            _out_variable_names = kparams.get('_out_variable_names',
                                              default_names)

            assert (len(_returns) == len(_out_variable_names))

            var_pair = zip(_out_variable_names, _returns)
            out_params = TypeInfo(var_pair)

        else:
            _out_variable_name = kparams.get(
                '_out_variable_name', '%s%s' % (func_name, RESULT_SUFFIX))

            out_params[_out_variable_name] = _returns

    ns = DEFAULT_NS
    if _out_message_name.startswith("{"):
        ns = _out_message_name[1:].partition("}")[0]

    if _body_style == 'bare' and _returns is not None:
        message = ComplexModel.alias(_out_message_name, ns, _returns)

    else:
        message = ComplexModel.produce(type_name=_out_message_name,
                                       namespace=ns,
                                       members=out_params)

        message.Attributes._wrapper = True
        message.__namespace__ = ns  # FIXME: is this necessary?

    return message
    def reorder_type_info(self, fields, type_info):
        """
        re-order the given type_info into the order given with fields. Anything
        not mentioned in fields, will be appended last.
        """

        copy = TypeInfo(type_info.items())
        new = TypeInfo()
        for field in fields:
            value = copy[field]
            del copy[field]
            new[field] = value

        # Add the fields not specified in fields last.
        for field, value in copy.items():
            new[field] = value
        return new
Exemple #13
0
    def reorder_type_info(self, fields, type_info):
        """
        re-order the given type_info into the order given with fields. Anything
        not mentioned in fields, will be appended last.
        """

        copy = TypeInfo(type_info.items())
        new = TypeInfo()
        for field in fields:
            value = copy[field]
            del copy[field]
            new[field] = value

        # Add the fields not specified in fields last.
        for field, value in copy.items():
            new[field] = value
        return new
Exemple #14
0
    def __new__(cls, cls_name, cls_bases, cls_dict):
        if cls_dict.get("__type_name__", None) is None:
            cls_dict["__type_name__"] = cls_name

        if cls_dict.get("_type_info", None) is None:
            cls_dict["_type_info"] = _type_info = TypeInfo()

            def check_mixin_inheritance(bases):
                for b in bases:
                    check_mixin_inheritance(b.__bases__)

                    for k, v in vars(b).items():
                        if _is_interesting(k, v):
                            _type_info[k] = _process_item(v)

            check_mixin_inheritance(cls_bases)

            def check_same_table_inheritance(bases):
                for b in bases:
                    check_same_table_inheritance(b.__bases__)

                    table = getattr(b, '__table__', None)

                    if not (table is None):
                        for c in table.c:
                            _type_info[c.name] = _process_item(c)

            check_same_table_inheritance(cls_bases)

            # include from table
            table = cls_dict.get('__table__', None)
            if not (table is None):
                for c in table.c:
                    _type_info[c.name] = _process_item(c)

            # own attributes
            for k, v in cls_dict.items():
                if _is_interesting(k, v):
                    _type_info[k] = _process_item(v)

        return super(TableModelMeta, cls).__new__(cls, cls_name, cls_bases,
                                                  cls_dict)
Exemple #15
0
def _produce_input_message(f, params, kparams, _in_message_name,
                           _in_variable_names, no_ctx):
    _body_style = _validate_body_style(kparams)

    if no_ctx is True:
        arg_start = 0
    else:
        arg_start = 1

    argcount = f.func_code.co_argcount
    param_names = f.func_code.co_varnames[arg_start:argcount]

    in_params = TypeInfo()
    try:
        for i in range(len(param_names)):
            e0 = _in_variable_names.get(param_names[i], param_names[i])
            e1 = params[i]

            in_params[e0] = e1

    except IndexError, e:
        raise Exception("The parameter numbers of the %r function and its "
                        "decorator mismatch." % f.func_name)
    def create_object_model(self, stuf_entiteit=None, topfundamenteel=False):
        """
        From a StUFEntiteit create a hierarchy of ComplexModels for everything under the object element.
        """
        stuf_entiteit = stuf_entiteit or self.stuf_entiteit

        type_info = TypeInfo()
        if stuf_entiteit.is_entiteit():
            type_info['entiteittype'] = entiteittype.customize(fixed=stuf_entiteit.get_mnemonic())
            type_info['verwerkingssoort'] = verwerkingssoort

        for related_field in stuf_entiteit.get_related_fields():
            # In the case of an update the element can be optional (since it isn't modified)
            model_kwargs = {
                'min_occurs': 0,
                'max_occurs': related_field.max_occurs or 'unbounded'
            }
            # On create, the min_occurs _is_ required.
            if not self.update:  # Create
                model_kwargs['min_occurs'] = related_field.min_occurs

            type_info[related_field.field_name] = self.create_object_model(
                related_field.stuf_entiteit).customize(**model_kwargs)

        # TODO [TECH]: In the WSDL this should be minOccurs and maxOccurs of 1.
        gerelateerde = stuf_entiteit.get_gerelateerde()
        if gerelateerde:
            _, gerelateerde_data = gerelateerde
            type_info['gerelateerde'] = self.create_related_model(stuf_entiteit, 'gerelateerde', gerelateerde_data)

        # Build up spyne model
        field_mapping = stuf_entiteit.get_django_field_mapping()
        file_fields = stuf_entiteit.get_file_fields()
        for field_name, django_field_name, django_field in field_mapping:
            #
            # These field requirement rules are not exactly as the KING XSD defines them,
            # but they're close enough (TM). On the highest level (topfundamenteel)
            # and on a 'creeer' service only a 'T' (create) can be done, so all django
            # required fields, are required for that, on the lower levels a 'I' might
            # be done, so not all fields are required.
            #
            if topfundamenteel and not self.update:  # create topfundamenteel -> read the Django field definitions
                customize_kwargs = {}
            else:
                required = False
                customize_kwargs = dict(
                    nullable=not required,
                    min_occurs=1 if required else 0
                )

            # TODO [TECH]: figure out if we can put this in the DJANGO -> SPYNE mapping
            if field_name in file_fields:
                spyne_model = BinaireInhoud.customize(**customize_kwargs)
            else:
                spyne_model = django_field_to_spyne_model(django_field, **customize_kwargs)

            type_info[field_name] = spyne_model

        for field_name, spyne_model, _ in stuf_entiteit.get_custom_fields():
            type_info[field_name] = spyne_model

        tijdvak_geldigheid = stuf_entiteit.get_tijdvak_geldigheid()
        if tijdvak_geldigheid:
            type_info.append(
                ('tijdvakGeldigheid', TijdvakGeldigheid.customize(ref='tijdvakGeldigheid')),
            )

        tijdvak_relatie = stuf_entiteit.get_tijdvak_relatie()
        if tijdvak_relatie:
            type_info.append(
                ('tijdvakRelatie', TijdvakRelatie.customize(ref='tijdvakRelatie')),
            )

        tijdstip_registratie = stuf_entiteit.get_tijdstip_registratie()
        if tijdstip_registratie:
            type_info.append(
                ('tijdstipRegistratie', Tijdstip_e.customize(ref='tijdstipRegistratie')),
            )

        complex_model = self.create_reusable_model(
            self.create_object_name(stuf_entiteit),
            stuf_entiteit.get_namespace(),
            type_info
        )

        complex_model._type_info = reorder_type_info(stuf_entiteit.get_fields(), complex_model._type_info)

        return complex_model
Exemple #17
0
        try:
            argcount = f.func_code.co_argcount
            param_names = f.func_code.co_varnames[arg_start:argcount]
        except AttributeError,e:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts."
            )

    else:
        argcount = len(args)
        param_names = args

    in_params = TypeInfo()
    try:
        for i, n in enumerate(param_names):
            if args is None or n in args:
                e0 = _in_variable_names.get(n,n)
                e1 = params[i]

                in_params[e0] = e1

    except IndexError, e:
        raise Exception("The parameter numbers of the %r function and its "
                        "decorator mismatch." % f.func_name)

    ns = DEFAULT_NS
    if _in_message_name.startswith("{"):
        ns, _, in_message_name = _in_message_name[1:].partition("}")
Exemple #18
0
    if args is None:
        try:
            argcount = f.func_code.co_argcount
            param_names = f.func_code.co_varnames[arg_start:argcount]
        except AttributeError, e:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts.")

    else:
        argcount = len(args)
        param_names = args

    in_params = TypeInfo()
    try:
        for i, n in enumerate(param_names):
            if args is None or n in args:
                e0 = _in_variable_names.get(n, n)
                e1 = params[i]

                in_params[e0] = e1

    except IndexError, e:
        raise Exception("The parameter numbers of the %r function and its "
                        "decorator mismatch." % f.func_name)

    ns = DEFAULT_NS
    if _in_message_name.startswith("{"):
        ns = _in_message_name[1:].partition("}")[0]
Exemple #19
0
def _produce_input_message(f, params, kparams, in_message_name,
                           in_variable_names, no_ctx, no_self, args):
    _body_style = _validate_body_style(kparams)

    arg_start = 0
    if no_ctx is False:
        arg_start += 1
    if no_self is False:
        arg_start += 1

    if args is None:
        try:
            argcount = f.__code__.co_argcount
            args = f.__code__.co_varnames[arg_start:argcount]

        except AttributeError:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts.")

        if len(params) != len(args):
            raise Exception("%r function has %d argument(s) but its decorator "
                            "has %d." % (f.__name__, len(args), len(params)))

    else:
        args = copy(args)
        if len(params) != len(args):
            raise Exception("%r function has %d argument(s) but the _args "
                            "argument has %d." %
                            (f.__name__, len(args), len(params)))

    in_params = TypeInfo()
    for k, v in zip(args, params):
        k = in_variable_names.get(k, k)
        in_params[k] = v

    ns = spyne.const.xml_ns.DEFAULT_NS
    if in_message_name.startswith("{"):
        ns, _, in_message_name = in_message_name[1:].partition("}")

    message = None
    if _body_style == 'bare':
        if len(in_params) > 1:
            raise Exception(
                "body_style='bare' can handle at most one function "
                "argument.")
        if len(in_params) == 0:
            message = ComplexModel.produce(type_name=in_message_name,
                                           namespace=ns,
                                           members=in_params)
        else:
            message, = in_params.values()
            message = message.customize(sub_name=in_message_name, sub_ns=ns)
            from spyne.model import ComplexModelBase
            if issubclass(message,
                          ComplexModelBase) and not message._type_info:
                raise Exception("body_style='bare' does not allow empty "
                                "model as param")

    else:
        message = ComplexModel.produce(type_name=in_message_name,
                                       namespace=ns,
                                       members=in_params)
        message.__namespace__ = ns

    return message
Exemple #20
0
def _produce_output_message(func_name, body_style_str, self_ref_cls, no_self,
                            kparams):
    """Generate an output message for "rpc"-style API methods.

    This message is a wrapper to the declared return type.
    """

    _returns = kparams.pop('_returns', None)

    try:
        is_self_ref = issubclass(_returns, SelfReference)
    except TypeError:
        is_self_ref = False

    if is_self_ref:
        if no_self is False:
            raise LogicError("SelfReference can't be used in @rpc")

        _returns = recust_selfref(_returns, self_ref_cls)

    _is_out_message_name_overridden = not ('_out_message_name' in kparams)
    _out_message_name = kparams.pop(
        '_out_message_name', '%s%s' % (func_name, spyne.const.RESPONSE_SUFFIX))

    if no_self is False and \
               (body_style_str == 'wrapped' or _is_out_message_name_overridden):
        _out_message_name = '%s.%s' % \
                               (self_ref_cls.get_type_name(), _out_message_name)

    out_params = TypeInfo()

    if _returns and body_style_str == 'wrapped':
        if isinstance(_returns, (list, tuple)):
            default_names = [
                '%s%s%d' % (func_name, spyne.const.RESULT_SUFFIX, i)
                for i in range(len(_returns))
            ]

            _out_variable_names = kparams.pop('_out_variable_names',
                                              default_names)

            assert (len(_returns) == len(_out_variable_names))

            var_pair = zip(_out_variable_names, _returns)
            out_params = TypeInfo(var_pair)

        else:
            _out_variable_name = kparams.pop(
                '_out_variable_name',
                '%s%s' % (func_name, spyne.const.RESULT_SUFFIX))

            out_params[_out_variable_name] = _returns

    ns = spyne.const.xml.DEFAULT_NS
    if _out_message_name.startswith("{"):
        _out_message_name_parts = _out_message_name[1:].partition("}")
        ns = _out_message_name_parts[0]  # skip index 1, it is the closing '}'
        _out_message_name = _out_message_name_parts[2]

    if body_style_str.endswith('bare') and _returns is not None:
        message = _returns.customize(sub_name=_out_message_name, sub_ns=ns)
        if message.__type_name__ is ModelBase.Empty:
            message.__type_name__ = _out_message_name

    else:
        message = ComplexModel.produce(type_name=_out_message_name,
                                       namespace=ns,
                                       members=out_params)

        message.Attributes._wrapper = True
        message.__namespace__ = ns  # FIXME: is this necessary?

    return message
    def create_object_model(self, stuf_entiteit=None):
        """
        From a StUFEntiteit create a hierarchy of ComplexModels for everything under the object element.
        """
        stuf_entiteit = stuf_entiteit or self.stuf_entiteit

        type_info = []
        if stuf_entiteit.is_entiteit():
            type_info.append(
                ('entiteittype', XmlAttribute(simple_types.Entiteittype, ref='entiteittype', ns=STUF_XML_NS))
            )

        tijdvak_geldigheid = stuf_entiteit.get_tijdvak_geldigheid()
        if tijdvak_geldigheid:
            type_info.append(
                ('tijdvakGeldigheid', TijdvakGeldigheid.customize(ref='tijdvakGeldigheid')),
            )

        tijdvak_relatie = stuf_entiteit.get_tijdvak_relatie()
        if tijdvak_relatie:
            type_info.append(
                ('tijdvakRelatie', TijdvakRelatie.customize(ref='tijdvakRelatie')),
            )

        tijdstip_registratie = stuf_entiteit.get_tijdstip_registratie()
        if tijdstip_registratie:
            type_info.append(
                ('tijdstipRegistratie', Tijdstip_e.customize(ref='tijdstipRegistratie')),
            )

        if getattr(stuf_entiteit, 'append_object_model', False):
            for key, append_complex_model in stuf_entiteit.append_object_model:
                # assert False, append_complex_model.__dict__
                type_info.append((key, append_complex_model))

        for related_field in stuf_entiteit.get_related_fields():
            type_info.append(
                (related_field.field_name, self.create_object_model(related_field.stuf_entiteit).customize(max_occurs='unbounded'))
            )

        # Create spyne model for 'gerelateerde'
        # TODO [TECH]: In the WSDL this should be minOccurs and maxOccurs of 1.
        gerelateerde = stuf_entiteit.get_gerelateerde()
        if gerelateerde:
            _, gerelateerde_data = gerelateerde
            if isinstance(gerelateerde_data, tuple) or isinstance(gerelateerde_data, list):
                sub_type_info = []
                for relation_name, related_cls in gerelateerde_data:
                    _object_model = self.create_object_model(related_cls).customize(xml_choice_group='gerelateerde')
                    sub_type_info.append((relation_name, _object_model))

                # See Stuf 03.01 - 3.2.2 De structuur van een object, why this model does not have a 'entiteittype'
                # attribute.
                #
                # Het element <gerelateerde> mag ook als kind een <choice> bevatten met twee of meer elementen
                # met een attribute StUF:entiteittype en daarbinnen de elementen voor dat entiteittype. Het element
                # <gerelateerde> heeft dan geen attributes.
                #
                sub_model = self.create_reusable_model(
                    self.create_object_name(stuf_entiteit, 'gerelateerde'),
                    stuf_entiteit.get_namespace(), sub_type_info
                ).customize(min_occurs=1, max_occurs=1)  # TODO [TECH]: min/max_occurs does not show up in the WSDL for some reason.
                type_info.append(('gerelateerde', sub_model))
            else:
                related_cls = gerelateerde_data
                # TODO [TECH]: min/max_occurs does not show up in the WSDL for some reason.
                type_info.append(('gerelateerde', self.create_object_model(related_cls).customize(min_occurs=1, max_occurs=1)))

        # Build up spyne model
        field_mapping = stuf_entiteit.get_django_field_mapping()
        new_type_info = TypeInfo()
        file_fields = stuf_entiteit.get_file_fields()
        required_fields = stuf_entiteit.get_required_fields()
        for field_name, _, django_field in field_mapping:
            if field_name in file_fields:
                new_type_info[field_name] = BinaireInhoud
            else:
                min_occurs = 1 if field_name in required_fields else 0
                new_type_info[field_name] = django_field_to_spyne_model(django_field, min_occurs=min_occurs)

        complex_model = self.create_reusable_model(
            self.create_object_name(stuf_entiteit),
            stuf_entiteit.get_namespace(), new_type_info
        )
        complex_model.stuf_entiteit = stuf_entiteit

        for k, v in type_info:
            complex_model._type_info[k] = v

        for field_name, spyne_model, _ in stuf_entiteit.get_custom_fields():
            complex_model._type_info[field_name] = spyne_model

        complex_model._type_info = reorder_type_info(stuf_entiteit.get_fields(), complex_model._type_info)

        return complex_model
Exemple #22
0
    def create_object_model(self, stuf_entiteit=None, topfundamenteel=False):
        """
        From a StUFEntiteit create a hierarchy of ComplexModels for everything under the object element.
        """
        stuf_entiteit = stuf_entiteit or self.stuf_entiteit

        type_info = TypeInfo()
        if stuf_entiteit.is_entiteit():
            type_info['entiteittype'] = entiteittype.customize(
                fixed=stuf_entiteit.get_mnemonic())
            type_info['verwerkingssoort'] = verwerkingssoort

        for related_field in stuf_entiteit.get_related_fields():
            # In the case of an update the element can be optional (since it isn't modified)
            model_kwargs = {
                'min_occurs': 0,
                'max_occurs': related_field.max_occurs or 'unbounded'
            }
            # On create, the min_occurs _is_ required.
            if not self.update:  # Create
                model_kwargs['min_occurs'] = related_field.min_occurs

            type_info[related_field.field_name] = self.create_object_model(
                related_field.stuf_entiteit).customize(**model_kwargs)

        # TODO [TECH]: In the WSDL this should be minOccurs and maxOccurs of 1.
        gerelateerde = stuf_entiteit.get_gerelateerde()
        if gerelateerde:
            _, gerelateerde_data = gerelateerde
            type_info['gerelateerde'] = self.create_related_model(
                stuf_entiteit, 'gerelateerde', gerelateerde_data)

        # Build up spyne model
        field_mapping = stuf_entiteit.get_django_field_mapping()
        file_fields = stuf_entiteit.get_file_fields()
        for field_name, django_field_name, django_field in field_mapping:
            #
            # These field requirement rules are not exactly as the KING XSD defines them,
            # but they're close enough (TM). On the highest level (topfundamenteel)
            # and on a 'creeer' service only a 'T' (create) can be done, so all django
            # required fields, are required for that, on the lower levels a 'I' might
            # be done, so not all fields are required.
            #
            if topfundamenteel and not self.update:  # create topfundamenteel -> read the Django field definitions
                customize_kwargs = {}
            else:
                required = False
                customize_kwargs = dict(nullable=not required,
                                        min_occurs=1 if required else 0)

            # TODO [TECH]: figure out if we can put this in the DJANGO -> SPYNE mapping
            if field_name in file_fields:
                spyne_model = BinaireInhoud.customize(**customize_kwargs)
            else:
                spyne_model = django_field_to_spyne_model(
                    django_field, **customize_kwargs)

            type_info[field_name] = spyne_model

        for field_name, spyne_model, _ in stuf_entiteit.get_custom_fields():
            type_info[field_name] = spyne_model

        tijdvak_geldigheid = stuf_entiteit.get_tijdvak_geldigheid()
        if tijdvak_geldigheid:
            type_info.append(
                ('tijdvakGeldigheid',
                 TijdvakGeldigheid.customize(ref='tijdvakGeldigheid')), )

        tijdvak_relatie = stuf_entiteit.get_tijdvak_relatie()
        if tijdvak_relatie:
            type_info.append(
                ('tijdvakRelatie',
                 TijdvakRelatie.customize(ref='tijdvakRelatie')), )

        tijdstip_registratie = stuf_entiteit.get_tijdstip_registratie()
        if tijdstip_registratie:
            type_info.append(
                ('tijdstipRegistratie',
                 Tijdstip_e.customize(ref='tijdstipRegistratie')), )

        complex_model = self.create_reusable_model(
            self.create_object_name(stuf_entiteit),
            stuf_entiteit.get_namespace(), type_info)

        complex_model._type_info = reorder_type_info(
            stuf_entiteit.get_fields(), complex_model._type_info)

        return complex_model
Exemple #23
0
def _produce_input_message(f, params, in_message_name, in_variable_names,
                       no_ctx, no_self, argnames, body_style_str, self_ref_cls,
                       in_wsdl_part_name):
    arg_start = 0
    if no_ctx is False:
        arg_start += 1
    if no_self is False:
        arg_start += 1

    if argnames is None:
        try:
            argcount = f.__code__.co_argcount
            argnames = f.__code__.co_varnames[arg_start:argcount]

        except AttributeError:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts."
            )

        if no_self is False:
            params = [self_ref_cls.novalidate_freq()] + params
            argnames = ('self',) + argnames

        if len(params) != len(argnames):
            raise LogicError("%r function has %d argument(s) but its decorator "
                           "has %d." % (f.__name__, len(argnames), len(params)))

    else:
        argnames = copy(argnames)
        if len(params) != len(argnames):
            raise LogicError("%r function has %d argument(s) but the _args "
                            "argument has %d." % (
                                f.__name__, len(argnames), len(params)))

    in_params = TypeInfo()
    from spyne import SelfReference
    for k, v in zip(argnames, params):
        try:
            is_self_ref = issubclass(v, SelfReference)
        except TypeError:
            is_self_ref = False

        if is_self_ref:
            if no_self is False:
                raise LogicError("SelfReference can't be used in @rpc")
            v = recust_selfref(v, self_ref_cls)

        k = in_variable_names.get(k, k)
        in_params[k] = v

    ns = spyne.const.xml.DEFAULT_NS
    if in_message_name.startswith("{"):
        ns, _, in_message_name = in_message_name[1:].partition("}")

    message = None
    if body_style_str == 'bare':
        if len(in_params) > 1:
            raise LogicError("body_style='bare' can handle at most one "
                                                           "function argument.")

        if len(in_params) == 0:
            message = ComplexModel.produce(type_name=in_message_name,
                                           namespace=ns, members=in_params)
        else:
            message, = in_params.values()
            message = message.customize(sub_name=in_message_name, sub_ns=ns)

            if issubclass(message, ComplexModelBase) and not message._type_info:
                raise LogicError("body_style='bare' does not allow empty "
                                                               "model as param")

            # there can't be multiple arguments here.
            if message.__type_name__ is ModelBase.Empty:
                message._fill_empty_type_name(ns, in_message_name,
                                                    "%s_arg0" % in_message_name)

    else:
        message = ComplexModel.produce(type_name=in_message_name,
                                       namespace=ns, members=in_params)
        message.__namespace__ = ns
    
    if in_wsdl_part_name:
        message = message.customize(wsdl_part_name=in_wsdl_part_name)

    return message
Exemple #24
0
def _produce_input_message(f, params, in_message_name, in_variable_names,
                           no_ctx, no_self, argnames, body_style_str,
                           self_ref_cls):
    arg_start = 0
    if no_ctx is False:
        arg_start += 1
    if no_self is False:
        arg_start += 1

    if argnames is None:
        try:
            argcount = f.__code__.co_argcount
            argnames = f.__code__.co_varnames[arg_start:argcount]

        except AttributeError:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts.")

        if no_self is False:
            params = [self_ref_cls.novalidate_freq()] + params
            argnames = ('self', ) + argnames

        if len(params) != len(argnames):
            raise LogicError(
                "%r function has %d argument(s) but its decorator "
                "has %d." % (f.__name__, len(argnames), len(params)))

    else:
        argnames = copy(argnames)
        if len(params) != len(argnames):
            raise LogicError("%r function has %d argument(s) but the _args "
                             "argument has %d." %
                             (f.__name__, len(argnames), len(params)))

    in_params = TypeInfo()
    from spyne import SelfReference
    for k, v in zip(argnames, params):
        try:
            is_self_ref = issubclass(v, SelfReference)
        except TypeError:
            is_self_ref = False

        if is_self_ref:
            if no_self is False:
                raise LogicError("SelfReference can't be used in @rpc")
            v = recust_selfref(v, self_ref_cls)

        k = in_variable_names.get(k, k)
        in_params[k] = v

    ns = spyne.const.xml.DEFAULT_NS
    if in_message_name.startswith("{"):
        ns, _, in_message_name = in_message_name[1:].partition("}")

    message = None
    if body_style_str == 'bare':
        if len(in_params) > 1:
            raise LogicError("body_style='bare' can handle at most one "
                             "function argument.")

        if len(in_params) == 0:
            message = ComplexModel.produce(type_name=in_message_name,
                                           namespace=ns,
                                           members=in_params)
        else:
            message, = in_params.values()
            message = message.customize(sub_name=in_message_name, sub_ns=ns)

            if issubclass(message,
                          ComplexModelBase) and not message._type_info:
                raise LogicError("body_style='bare' does not allow empty "
                                 "model as param")

            # there can't be multiple arguments here.
            if message.__type_name__ is ModelBase.Empty:
                message._fill_empty_type_name(ns, in_message_name,
                                              "%s_arg0" % in_message_name)

    else:
        message = ComplexModel.produce(type_name=in_message_name,
                                       namespace=ns,
                                       members=in_params)
        message.__namespace__ = ns

    return message
Exemple #25
0
 def test_update(self):
     d = TypeInfo()
     d["a"] = 1
     d.update([('b', 2)])
     assert d[0] == d['a'] == 1
     assert d[1] == d['b'] == 2
Exemple #26
0
    if args is None:
        try:
            argcount = f.func_code.co_argcount
            param_names = f.func_code.co_varnames[arg_start:argcount]
        except AttributeError,e:
            raise TypeError("It's not possible to instrospect builtins. You "
                            "must pass a sequence of argument names as the "
                            "'_args' argument to the rpc decorator to manually "
                            "denote the arguments that this function accepts."
                        )
    else:
        argcount = len(args)
        param_names = args

    in_params = TypeInfo()
    try:
        i=0
        for n in param_names:
            if args is None or n in args:
                e0 = _in_variable_names.get(n,n)
                e1 = params[i]

                in_params[e0] = e1
                i += 1

    except IndexError, e:
        raise Exception("The parameter numbers of the %r function and its "
                        "decorator mismatch." % f.func_name)

    ns = DEFAULT_NS
Exemple #27
0
        try:
            argcount = f.func_code.co_argcount
            param_names = f.func_code.co_varnames[arg_start:argcount]
        except AttributeError,e:
            raise TypeError(
                "It's not possible to instrospect builtins. You must pass a "
                "sequence of argument names as the '_args' argument to the "
                "rpc decorator to manually denote the arguments that this "
                "function accepts."
            )

    else:
        argcount = len(args)
        param_names = args

    in_params = TypeInfo()
    try:
        for i, n in enumerate(param_names):
            if args is None or n in args:
                e0 = _in_variable_names.get(n,n)
                e1 = params[i]

                in_params[e0] = e1

    except IndexError, e:
        raise Exception("The parameter numbers of the %r function and its "
                        "decorator mismatch." % f.func_name)

    ns = DEFAULT_NS
    if _in_message_name.startswith("{"):
        ns, _, _in_message_name = _in_message_name[1:].partition("}")
Exemple #28
0
 def test_update(self):
     d = TypeInfo()
     d["a"] = 1
     d.update([('b', 2)])
     assert d[0] == d['a'] == 1
     assert d[1] == d['b'] == 2