Skip to content

client

xsdata.formats.dataclass.client

Config dataclass

Service configuration class.

Attributes:

Name Type Description
style str

The binding style

location str

The service endpoint url

transport str

The transport namespace

soap_action str

The soap action

input Type

The input class

output Type

The output class

Source code in xsdata/formats/dataclass/client.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@dataclass(frozen=True)
class Config:
    """Service configuration class.

    Attributes:
        style: The binding style
        location: The service endpoint url
        transport: The transport namespace
        soap_action: The soap action
        input: The input class
        output: The output class
    """

    style: str
    location: str
    transport: str
    soap_action: str
    input: Type
    output: Type
    encoding: Optional[str] = None

    @classmethod
    def from_service(cls, obj: Any, **kwargs: Any) -> "Config":
        """Instantiate from a generated service class.

        Args:
            obj: The service class
            **kwargs: Override the service class properties
                style: The binding style
                location: The service endpoint url
                transport: The transport namespace
                soap_action: The soap action
                input: The input class
                output: The output class

        Returns:
            A new config instance.
        """
        params = {
            f.name: kwargs[f.name] if f.name in kwargs else getattr(obj, f.name, None)
            for f in fields(cls)
        }

        return cls(**params)

from_service(obj, **kwargs) classmethod

Instantiate from a generated service class.

Parameters:

Name Type Description Default
obj Any

The service class

required
**kwargs Any

Override the service class properties style: The binding style location: The service endpoint url transport: The transport namespace soap_action: The soap action input: The input class output: The output class

{}

Returns:

Type Description
Config

A new config instance.

Source code in xsdata/formats/dataclass/client.py
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@classmethod
def from_service(cls, obj: Any, **kwargs: Any) -> "Config":
    """Instantiate from a generated service class.

    Args:
        obj: The service class
        **kwargs: Override the service class properties
            style: The binding style
            location: The service endpoint url
            transport: The transport namespace
            soap_action: The soap action
            input: The input class
            output: The output class

    Returns:
        A new config instance.
    """
    params = {
        f.name: kwargs[f.name] if f.name in kwargs else getattr(obj, f.name, None)
        for f in fields(cls)
    }

    return cls(**params)

TransportTypes

Transport types.

Source code in xsdata/formats/dataclass/client.py
57
58
59
60
class TransportTypes:
    """Transport types."""

    SOAP = "http://schemas.xmlsoap.org/soap/http"

Client

A wsdl client.

Parameters:

Name Type Description Default
config Config

The service config instance

required
transport Optional[Transport]

The transport instance

None
parser Optional[XmlParser]

The xml parser instance

None
serializer Optional[XmlSerializer]

The xml serializer instance

None
Source code in xsdata/formats/dataclass/client.py
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
class Client:
    """A wsdl client.

    Args:
        config: The service config instance
        transport: The transport instance
        parser: The xml parser instance
        serializer: The xml serializer instance
    """

    __slots__ = "config", "transport", "parser", "serializer"

    def __init__(
        self,
        config: Config,
        transport: Optional[Transport] = None,
        parser: Optional[XmlParser] = None,
        serializer: Optional[XmlSerializer] = None,
    ):
        self.config = config
        self.transport = transport or DefaultTransport()

        if not serializer and not parser:
            context = XmlContext()
            serializer = XmlSerializer(context=context)
            parser = XmlParser(context=context)
        elif not serializer:
            assert parser is not None
            serializer = XmlSerializer(context=parser.context)
        else:
            assert serializer is not None
            parser = XmlParser(context=serializer.context)

        self.parser = parser
        self.serializer = serializer

    @classmethod
    def from_service(cls, obj: Type, **kwargs: Any) -> "Client":
        """Instantiate client from a service class.

        Args:
            obj: The service class
            **kwargs: Override the service class properties
                style: The binding style
                location: The service endpoint url
                transport: The transport namespace
                soap_action: The soap action
                input: The input class
                output: The output class

        Returns:
            A new client instance.
        """
        return cls(config=Config.from_service(obj, **kwargs))

    def send(self, obj: Any, headers: Optional[Dict] = None) -> Any:
        """Build and send a request for the input object.

        ```py
        params = {"body": {"add": {"int_a": 3, "int_b": 4}}}
        res = client.send(params)
        ```
        Is equivalent with:

        ```py
        req = CalculatorSoapAddInput(
        body=CalculatorSoapAddInput.Body(add=Add(3, 4)))
        res = client.send(req)
        ```

        Args:
            obj: The request model instance or a pure dictionary
            headers: Additional headers to pass to the transport

        Returns:
            The response model instance.
        """
        data = self.prepare_payload(obj)
        headers = self.prepare_headers(headers or {})
        response = self.transport.post(self.config.location, data=data, headers=headers)
        return self.parser.from_bytes(response, self.config.output)

    def prepare_headers(self, headers: Dict) -> Dict:
        """Prepare the request headers.

        It merges the custom user headers with the necessary headers
        to accommodate the service class configuration.

        Raises:
            ClientValueError: If the service transport type is not supported.
        """
        result = headers.copy()
        if self.config.transport == TransportTypes.SOAP:
            result["content-type"] = "text/xml"
            if self.config.soap_action:
                result["SOAPAction"] = self.config.soap_action
        else:
            raise ClientValueError(
                f"Unsupported binding transport: `{self.config.transport}`"
            )

        return result

    def prepare_payload(self, obj: Any) -> Union[str, bytes]:
        """Prepare and serialize the payload to be sent.

        If the obj is a pure dictionary, it will be converted
        first to a request model instance.

        Args:
            obj: The request model instance or a pure dictionary

        Returns:
            The serialized request body content as string or bytes.

        Raises:
            ClientValueError: If the config input type doesn't match the given object.
        """
        if isinstance(obj, Dict):
            decoder = DictDecoder(context=self.serializer.context)
            obj = decoder.decode(obj, self.config.input)

        if not isinstance(obj, self.config.input):
            raise ClientValueError(
                f"Invalid input service type, "
                f"expected `{self.config.input.__name__}` "
                f"got `{type(obj).__name__}`"
            )

        result = self.serializer.render(obj)
        if self.config.encoding:
            return result.encode(self.config.encoding)

        return result

from_service(obj, **kwargs) classmethod

Instantiate client from a service class.

Parameters:

Name Type Description Default
obj Type

The service class

required
**kwargs Any

Override the service class properties style: The binding style location: The service endpoint url transport: The transport namespace soap_action: The soap action input: The input class output: The output class

{}

Returns:

Type Description
Client

A new client instance.

Source code in xsdata/formats/dataclass/client.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@classmethod
def from_service(cls, obj: Type, **kwargs: Any) -> "Client":
    """Instantiate client from a service class.

    Args:
        obj: The service class
        **kwargs: Override the service class properties
            style: The binding style
            location: The service endpoint url
            transport: The transport namespace
            soap_action: The soap action
            input: The input class
            output: The output class

    Returns:
        A new client instance.
    """
    return cls(config=Config.from_service(obj, **kwargs))

send(obj, headers=None)

Build and send a request for the input object.

params = {"body": {"add": {"int_a": 3, "int_b": 4}}}
res = client.send(params)
Is equivalent with:

req = CalculatorSoapAddInput(
body=CalculatorSoapAddInput.Body(add=Add(3, 4)))
res = client.send(req)

Parameters:

Name Type Description Default
obj Any

The request model instance or a pure dictionary

required
headers Optional[Dict]

Additional headers to pass to the transport

None

Returns:

Type Description
Any

The response model instance.

Source code in xsdata/formats/dataclass/client.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
def send(self, obj: Any, headers: Optional[Dict] = None) -> Any:
    """Build and send a request for the input object.

    ```py
    params = {"body": {"add": {"int_a": 3, "int_b": 4}}}
    res = client.send(params)
    ```
    Is equivalent with:

    ```py
    req = CalculatorSoapAddInput(
    body=CalculatorSoapAddInput.Body(add=Add(3, 4)))
    res = client.send(req)
    ```

    Args:
        obj: The request model instance or a pure dictionary
        headers: Additional headers to pass to the transport

    Returns:
        The response model instance.
    """
    data = self.prepare_payload(obj)
    headers = self.prepare_headers(headers or {})
    response = self.transport.post(self.config.location, data=data, headers=headers)
    return self.parser.from_bytes(response, self.config.output)

prepare_headers(headers)

Prepare the request headers.

It merges the custom user headers with the necessary headers to accommodate the service class configuration.

Raises:

Type Description
ClientValueError

If the service transport type is not supported.

Source code in xsdata/formats/dataclass/client.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
def prepare_headers(self, headers: Dict) -> Dict:
    """Prepare the request headers.

    It merges the custom user headers with the necessary headers
    to accommodate the service class configuration.

    Raises:
        ClientValueError: If the service transport type is not supported.
    """
    result = headers.copy()
    if self.config.transport == TransportTypes.SOAP:
        result["content-type"] = "text/xml"
        if self.config.soap_action:
            result["SOAPAction"] = self.config.soap_action
    else:
        raise ClientValueError(
            f"Unsupported binding transport: `{self.config.transport}`"
        )

    return result

prepare_payload(obj)

Prepare and serialize the payload to be sent.

If the obj is a pure dictionary, it will be converted first to a request model instance.

Parameters:

Name Type Description Default
obj Any

The request model instance or a pure dictionary

required

Returns:

Type Description
Union[str, bytes]

The serialized request body content as string or bytes.

Raises:

Type Description
ClientValueError

If the config input type doesn't match the given object.

Source code in xsdata/formats/dataclass/client.py
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
def prepare_payload(self, obj: Any) -> Union[str, bytes]:
    """Prepare and serialize the payload to be sent.

    If the obj is a pure dictionary, it will be converted
    first to a request model instance.

    Args:
        obj: The request model instance or a pure dictionary

    Returns:
        The serialized request body content as string or bytes.

    Raises:
        ClientValueError: If the config input type doesn't match the given object.
    """
    if isinstance(obj, Dict):
        decoder = DictDecoder(context=self.serializer.context)
        obj = decoder.decode(obj, self.config.input)

    if not isinstance(obj, self.config.input):
        raise ClientValueError(
            f"Invalid input service type, "
            f"expected `{self.config.input.__name__}` "
            f"got `{type(obj).__name__}`"
        )

    result = self.serializer.render(obj)
    if self.config.encoding:
        return result.encode(self.config.encoding)

    return result