mms-client 1.3.0__tar.gz → 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mms_client-1.3.0 → mms_client-1.4.0}/PKG-INFO +24 -3
- {mms_client-1.3.0 → mms_client-1.4.0}/README.md +23 -2
- {mms_client-1.3.0 → mms_client-1.4.0}/pyproject.toml +1 -1
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/services/base.py +12 -1
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/base.py +1 -1
- mms_client-1.4.0/src/mms_client/utils/auditing.py +54 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/utils/web.py +7 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/LICENSE +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/__init__.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/client.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/py.typed +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/wsdl/mi-web-service-jbms.wsdl +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/wsdl/omi-web-service.wsdl +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/xsd/mi-market.xsd +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/xsd/mi-outbnd-reports.xsd +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/xsd/mi-report.xsd +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/xsd/mpr.xsd +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/schemas/xsd/omi.xsd +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/security/__init__.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/security/certs.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/security/crypto.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/services/__init__.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/services/market.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/services/omi.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/services/registration.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/services/report.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/__init__.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/award.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/enums.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/fields.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/market.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/offer.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/registration.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/resource.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/types/transport.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/utils/__init__.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/utils/errors.py +0 -0
- {mms_client-1.3.0 → mms_client-1.4.0}/src/mms_client/utils/serialization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mms-client
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: API client for accessing the MMS
|
|
5
5
|
Home-page: https://github.com/ElectroRoute-Japan/mms-client
|
|
6
6
|
Author: Ryan Wood
|
|
@@ -174,14 +174,14 @@ There's a lot of code here but it's not terribly difficult to understand. All th
|
|
|
174
174
|
If you want to test your MMS connection, you can try using the test server:
|
|
175
175
|
|
|
176
176
|
```python
|
|
177
|
-
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert,
|
|
177
|
+
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, test=True)
|
|
178
178
|
```
|
|
179
179
|
|
|
180
180
|
## Connecting as a Market Admin
|
|
181
181
|
If you're connecting as a market operator (MO), you can connect in admin mode:
|
|
182
182
|
|
|
183
183
|
```python
|
|
184
|
-
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert,
|
|
184
|
+
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, is_admin=True)
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
## Log Settings
|
|
@@ -193,6 +193,27 @@ client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.B
|
|
|
193
193
|
|
|
194
194
|
The client currently logs a number of informational, debug and error messages. You can freely change the logging level yourself.
|
|
195
195
|
|
|
196
|
+
## Auditing XML Requests & Responses
|
|
197
|
+
A common requirement for this sort of library is recording or saving the raw XML requests and responses for audit/logging purposes. This library supports this workflow through the `mms_client.utils.auditing.AuditPlugin` object. This object intercepts the XML request at the Zeep client level right before it is sent to the MMS and, similarly, intercepts the XML response immediately after it is received from the MMS. Before passing these objects on, without modifying them, it records the XML data as a byte string and passes it to two methods: `audit_request` and `audit_response`. These can be overridden by any object that inherits from this class, allowing the user to direct this data to whatever store they prefer to use for auditing or logging.
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
class TestAuditPlugin(AuditPlugin):
|
|
201
|
+
|
|
202
|
+
def __init__(self):
|
|
203
|
+
self.request = None
|
|
204
|
+
self.response = None
|
|
205
|
+
|
|
206
|
+
def audit_request(self, mms_request: bytes) -> None:
|
|
207
|
+
self.request = mms_request
|
|
208
|
+
|
|
209
|
+
def audit_response(self, mms_response: bytes) -> None:
|
|
210
|
+
self.response = mms_response
|
|
211
|
+
|
|
212
|
+
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, plugins=[TestAuditPlugin()])
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
This same input allows for the user to create their own plugins and add them to the Zeep client, allowing for a certain amount of extensibility.
|
|
216
|
+
|
|
196
217
|
# Completeness
|
|
197
218
|
This client is not complete. Currently, it supports the following endpoints:
|
|
198
219
|
- MarketSubmit_OfferData
|
|
@@ -142,14 +142,14 @@ There's a lot of code here but it's not terribly difficult to understand. All th
|
|
|
142
142
|
If you want to test your MMS connection, you can try using the test server:
|
|
143
143
|
|
|
144
144
|
```python
|
|
145
|
-
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert,
|
|
145
|
+
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, test=True)
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
## Connecting as a Market Admin
|
|
149
149
|
If you're connecting as a market operator (MO), you can connect in admin mode:
|
|
150
150
|
|
|
151
151
|
```python
|
|
152
|
-
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert,
|
|
152
|
+
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, is_admin=True)
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
## Log Settings
|
|
@@ -161,6 +161,27 @@ client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.B
|
|
|
161
161
|
|
|
162
162
|
The client currently logs a number of informational, debug and error messages. You can freely change the logging level yourself.
|
|
163
163
|
|
|
164
|
+
## Auditing XML Requests & Responses
|
|
165
|
+
A common requirement for this sort of library is recording or saving the raw XML requests and responses for audit/logging purposes. This library supports this workflow through the `mms_client.utils.auditing.AuditPlugin` object. This object intercepts the XML request at the Zeep client level right before it is sent to the MMS and, similarly, intercepts the XML response immediately after it is received from the MMS. Before passing these objects on, without modifying them, it records the XML data as a byte string and passes it to two methods: `audit_request` and `audit_response`. These can be overridden by any object that inherits from this class, allowing the user to direct this data to whatever store they prefer to use for auditing or logging.
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
class TestAuditPlugin(AuditPlugin):
|
|
169
|
+
|
|
170
|
+
def __init__(self):
|
|
171
|
+
self.request = None
|
|
172
|
+
self.response = None
|
|
173
|
+
|
|
174
|
+
def audit_request(self, mms_request: bytes) -> None:
|
|
175
|
+
self.request = mms_request
|
|
176
|
+
|
|
177
|
+
def audit_response(self, mms_response: bytes) -> None:
|
|
178
|
+
self.response = mms_response
|
|
179
|
+
|
|
180
|
+
client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, plugins=[TestAuditPlugin()])
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This same input allows for the user to create their own plugins and add them to the Zeep client, allowing for a certain amount of extensibility.
|
|
184
|
+
|
|
164
185
|
# Completeness
|
|
165
186
|
This client is not complete. Currently, it supports the following endpoints:
|
|
166
187
|
- MarketSubmit_OfferData
|
|
@@ -33,6 +33,7 @@ from mms_client.utils.errors import MMSValidationError
|
|
|
33
33
|
from mms_client.utils.serialization import Serializer
|
|
34
34
|
from mms_client.utils.web import ClientType
|
|
35
35
|
from mms_client.utils.web import Interface
|
|
36
|
+
from mms_client.utils.web import Plugin
|
|
36
37
|
from mms_client.utils.web import ZWrapper
|
|
37
38
|
|
|
38
39
|
# Set the default logger for the MMS client
|
|
@@ -253,6 +254,7 @@ class BaseClient: # pylint: disable=too-many-instance-attributes
|
|
|
253
254
|
client_type: ClientType,
|
|
254
255
|
cert: Certificate,
|
|
255
256
|
logger: Optional[Logger] = None,
|
|
257
|
+
plugins: Optional[List[Plugin]] = None,
|
|
256
258
|
is_admin: bool = False,
|
|
257
259
|
test: bool = False,
|
|
258
260
|
):
|
|
@@ -265,6 +267,8 @@ class BaseClient: # pylint: disable=too-many-instance-attributes
|
|
|
265
267
|
cert (Certificate): The certificate to use for signing requests.
|
|
266
268
|
logger (Logger): The logger to use for instrumentation. If this is not provided, then the default
|
|
267
269
|
logger will be used.
|
|
270
|
+
plugins (List[Plugin]): A list of plugins to add to the Zeep client. This can be useful for auditing or
|
|
271
|
+
other purposes.
|
|
268
272
|
is_admin (bool): Whether the user is an admin (i.e. is a market operator).
|
|
269
273
|
test (bool): Whether to use the test server.
|
|
270
274
|
"""
|
|
@@ -281,6 +285,7 @@ class BaseClient: # pylint: disable=too-many-instance-attributes
|
|
|
281
285
|
|
|
282
286
|
# Now, set our logger to either the provided logger or the default logger
|
|
283
287
|
self._logger = logger or default_logger
|
|
288
|
+
self._plugins = plugins or []
|
|
284
289
|
|
|
285
290
|
# Finally, create a list of wrappers for the different interfaces
|
|
286
291
|
self._wrappers: Dict[Interface, ZWrapper] = {}
|
|
@@ -598,6 +603,12 @@ class BaseClient: # pylint: disable=too-many-instance-attributes
|
|
|
598
603
|
if service.interface not in self._wrappers:
|
|
599
604
|
self._logger.debug(f"Creating wrapper for {service.interface.name} interface.")
|
|
600
605
|
self._wrappers[service.interface] = ZWrapper(
|
|
601
|
-
self._client_type,
|
|
606
|
+
self._client_type,
|
|
607
|
+
service.interface,
|
|
608
|
+
self._cert.to_adapter(),
|
|
609
|
+
self._logger,
|
|
610
|
+
self._plugins,
|
|
611
|
+
True,
|
|
612
|
+
self._test,
|
|
602
613
|
)
|
|
603
614
|
return self._wrappers[service.interface]
|
|
@@ -115,7 +115,7 @@ class SchemaType(Enum):
|
|
|
115
115
|
OMI = "omi.xsd"
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
class PayloadBase(BaseXmlModel, nsmap={"xsi": "http://www.w3.org/2001/XMLSchema"}):
|
|
118
|
+
class PayloadBase(BaseXmlModel, nsmap={"xsi": "http://www.w3.org/2001/XMLSchema-instance"}):
|
|
119
119
|
"""Represents the base fields for an MMS request payload."""
|
|
120
120
|
|
|
121
121
|
# The XML schema to use for validation
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Contains functions for auditability plugins."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from abc import abstractmethod
|
|
5
|
+
|
|
6
|
+
from lxml.etree import _Element as Element
|
|
7
|
+
from lxml.etree import tostring
|
|
8
|
+
from zeep import Plugin
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AuditPlugin(ABC, Plugin):
|
|
12
|
+
"""Base class for audit plugins."""
|
|
13
|
+
|
|
14
|
+
def egress(self, envelope: Element, http_headers: dict, operation, binding_options):
|
|
15
|
+
"""Handle the MMS request before it is sent.
|
|
16
|
+
|
|
17
|
+
Arguments are the same as in the egress method of the Plugin class.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
lxml.etree.Element: The XML message to send.
|
|
21
|
+
dict: The HTTP headers to send.
|
|
22
|
+
"""
|
|
23
|
+
data = tostring(envelope, encoding="UTF-8", xml_declaration=True)
|
|
24
|
+
self.audit_request(data)
|
|
25
|
+
return envelope, http_headers
|
|
26
|
+
|
|
27
|
+
def ingress(self, envelope: Element, http_headers: dict, operation):
|
|
28
|
+
"""Handle the MMS response before it is processed.
|
|
29
|
+
|
|
30
|
+
Arguments are the same as in the ingress method of the Plugin class.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
lxml.etree.Element: The XML message to process.
|
|
34
|
+
dict: The HTTP headers to process.
|
|
35
|
+
"""
|
|
36
|
+
data = tostring(envelope, encoding="UTF-8", xml_declaration=True)
|
|
37
|
+
self.audit_response(data)
|
|
38
|
+
return envelope, http_headers
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def audit_request(self, mms_request: bytes) -> None:
|
|
42
|
+
"""Audit an MMS request.
|
|
43
|
+
|
|
44
|
+
Arguments:
|
|
45
|
+
mms_request (bytes): The MMS request XML to audit.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def audit_response(self, mms_response: bytes) -> None:
|
|
50
|
+
"""Audit an MMS response.
|
|
51
|
+
|
|
52
|
+
Arguments:
|
|
53
|
+
mms_response (bytes): The MMS response XML to audit.
|
|
54
|
+
"""
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from logging import Logger
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from typing import List
|
|
7
|
+
from typing import Optional
|
|
6
8
|
|
|
7
9
|
from backoff import expo
|
|
8
10
|
from backoff import on_exception
|
|
9
11
|
from requests import Session
|
|
10
12
|
from requests_pkcs12 import Pkcs12Adapter
|
|
11
13
|
from zeep import Client
|
|
14
|
+
from zeep import Plugin
|
|
12
15
|
from zeep import Transport
|
|
13
16
|
from zeep.cache import SqliteCache
|
|
14
17
|
from zeep.exceptions import TransportError
|
|
@@ -132,6 +135,7 @@ class ZWrapper:
|
|
|
132
135
|
interface: Interface,
|
|
133
136
|
adapter: Pkcs12Adapter,
|
|
134
137
|
logger: Logger,
|
|
138
|
+
plugins: Optional[List[Plugin]] = None,
|
|
135
139
|
cache: bool = True,
|
|
136
140
|
test: bool = False,
|
|
137
141
|
):
|
|
@@ -147,6 +151,8 @@ class ZWrapper:
|
|
|
147
151
|
adapter (Pkcs12Adapter): The PKCS12 adapter containing the certificate and private key to use for
|
|
148
152
|
authenticating with the MMS server.
|
|
149
153
|
logger (Logger): The logger to use for instrumentation.
|
|
154
|
+
plugins (List[Plugin]): A list of Zeep plugins to use with the client. This is useful for adding additional
|
|
155
|
+
functionality to the client, such as auditing or logging.
|
|
150
156
|
cache (bool): If True, use a cache for the Zeep client. This is useful for avoiding repeated
|
|
151
157
|
lookups of the WSDL file, which should result in lower latency.
|
|
152
158
|
test (bool): If True, use the test service endpoint. This is useful for testing the client.
|
|
@@ -184,6 +190,7 @@ class ZWrapper:
|
|
|
184
190
|
self._client = Client(
|
|
185
191
|
wsdl=str(location.resolve()),
|
|
186
192
|
transport=Transport(cache=SqliteCache() if cache else None, session=sess),
|
|
193
|
+
plugins=plugins,
|
|
187
194
|
)
|
|
188
195
|
self._create_service()
|
|
189
196
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|