mms-client 1.3.1__py3-none-any.whl → 1.4.0__py3-none-any.whl

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.
@@ -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, service.interface, self._cert.to_adapter(), self._logger, True, self._test
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]
@@ -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
+ """
mms_client/utils/web.py CHANGED
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mms-client
3
- Version: 1.3.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
@@ -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
@@ -12,7 +12,7 @@ mms_client/security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
12
12
  mms_client/security/certs.py,sha256=kNCUFmy18YIxkWKu3mdMmlxmHdft4a6BvtyJ46rA9I4,1489
13
13
  mms_client/security/crypto.py,sha256=M7aIllM3_ZwZgm9nH6QQ6Ig14XCAd6e6WGwqqUbbI1Q,2149
14
14
  mms_client/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- mms_client/services/base.py,sha256=mcUL-AZpaJETVkzAOoazmKfI5O3cJ0KWzIYQ5bjpNuE,25839
15
+ mms_client/services/base.py,sha256=LVAZSIBunvTPoC8BquC1TEUauIcSA7ePZhIrcOFg2aE,26245
16
16
  mms_client/services/market.py,sha256=aIWi52BFvDmtuipKnSZNprwbFYGYBcV6sZCQqMR_D2g,7574
17
17
  mms_client/services/omi.py,sha256=h6cM5U3-iSm0YiIaJwqYTZeI5uhLbA7FPxh_qy_3qww,521
18
18
  mms_client/services/registration.py,sha256=46Scntwlc9CtCO-tV6uEnr4NrVGJiUqhvksII13CGAE,3651
@@ -28,10 +28,11 @@ mms_client/types/registration.py,sha256=Nir73S3ffpk0O_fnTD2alFaqV1k67_8dcyyduXvP
28
28
  mms_client/types/resource.py,sha256=TQnY3JLHRgQhQrG6ISquw-BQgKSr8TGuqn9ItWxWz_w,65974
29
29
  mms_client/types/transport.py,sha256=DPjWs34UW915GkUCJWKuDZmsjS6mRdRXgcGISduN_Bc,4399
30
30
  mms_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ mms_client/utils/auditing.py,sha256=nRa2SI21B3N3ZhbGhgooHAPZ81J1NZ9e4JU1ucEKM-g,1693
31
32
  mms_client/utils/errors.py,sha256=jYdlG4OPI82s0fJcXCRNlKeEixDUSSAxjs_7C16qVL4,2306
32
33
  mms_client/utils/serialization.py,sha256=vTJZSjhfTph2tDAYbLAhnz89i0qXJ8FINGdve67cJOU,29534
33
- mms_client/utils/web.py,sha256=fcdCtdDrHBPyhIlTcyiuAk3D3TlW8HmUw-wGfpG4KTA,9653
34
- mms_client-1.3.1.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
35
- mms_client-1.3.1.dist-info/METADATA,sha256=oSdqfUgW01Tr2ZRcCUd4SedQzQZrvNLY5fWmNmlMviY,14774
36
- mms_client-1.3.1.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
37
- mms_client-1.3.1.dist-info/RECORD,,
34
+ mms_client/utils/web.py,sha256=KtG2ffQL14eOyNfiipGHB5dSotS32ecTLmS-7gnyX1g,10020
35
+ mms_client-1.4.0.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
36
+ mms_client-1.4.0.dist-info/METADATA,sha256=mkJwPYQwunR0QRLqRZmCybkiCiM_FirlqrvnBx7AQXg,16154
37
+ mms_client-1.4.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
38
+ mms_client-1.4.0.dist-info/RECORD,,