mms-client 1.6.0__py3-none-any.whl → 1.8.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.
mms_client/utils/web.py CHANGED
@@ -12,13 +12,13 @@ from requests import Session
12
12
  from requests_pkcs12 import Pkcs12Adapter
13
13
  from zeep import Client
14
14
  from zeep import Plugin
15
- from zeep import Transport
16
15
  from zeep.cache import SqliteCache
17
16
  from zeep.exceptions import TransportError
18
17
  from zeep.xsd.valueobjects import CompoundValue
19
18
 
20
19
  from mms_client.types.transport import MmsRequest
21
20
  from mms_client.types.transport import MmsResponse
21
+ from mms_client.utils.multipart_transport import MultipartTransport
22
22
 
23
23
  # Set the default logger for the MMS client
24
24
  logger = getLogger(__name__)
@@ -134,6 +134,7 @@ class ZWrapper:
134
134
 
135
135
  def __init__(
136
136
  self,
137
+ domain: str,
137
138
  client: ClientType,
138
139
  interface: Interface,
139
140
  adapter: Pkcs12Adapter,
@@ -144,6 +145,7 @@ class ZWrapper:
144
145
  """Create a new Zeep wrapper object for a specific MMS service endpoint.
145
146
 
146
147
  Arguments:
148
+ domain (str): The domain to use when signing the content ID to MTOM attachments.
147
149
  client (ClientType): The type of client to use. This can be either "bsp" (Balancing Service Provider) or
148
150
  "tso" (Transmission System Operator). This will determine which service endpoint to
149
151
  use.
@@ -191,13 +193,25 @@ class ZWrapper:
191
193
 
192
194
  # Finally, we create the Zeep client with the given WSDL file location, session, and cache settings and then,
193
195
  # from that client, we create the SOAP service with the given service binding and selected endpoint.
196
+ self._transport = MultipartTransport(domain, cache=SqliteCache() if cache else None, session=sess)
194
197
  self._client = Client(
195
198
  wsdl=str(location.resolve()),
196
- transport=Transport(cache=SqliteCache() if cache else None, session=sess),
199
+ transport=self._transport,
197
200
  plugins=plugins,
198
201
  )
199
202
  self._create_service()
200
203
 
204
+ def register_attachment(self, name: str, attachment: bytes) -> str:
205
+ """Register a multipart attachment.
206
+
207
+ Arguments:
208
+ name (str): The name of the attachment.
209
+ attachment (bytes): The data to be attached.
210
+
211
+ Returns: The content ID of the attachment, which should be used in place of the attachment data.
212
+ """
213
+ return self._transport.register_attachment(name, attachment)
214
+
201
215
  @on_exception(expo, TransportError, max_tries=3, giveup=fatal_code, logger=logger) # type: ignore[arg-type]
202
216
  def submit(self, req: MmsRequest) -> MmsResponse:
203
217
  """Submit the given request to the MMS server and return the response.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mms-client
3
- Version: 1.6.0
3
+ Version: 1.8.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
@@ -22,7 +22,9 @@ Requires-Dist: backoff (>=2.2.1,<3.0.0)
22
22
  Requires-Dist: cryptography (>=42.0.5,<43.0.0)
23
23
  Requires-Dist: lxml (>=5.1.0,<6.0.0)
24
24
  Requires-Dist: pendulum (>=3.0.0,<4.0.0)
25
+ Requires-Dist: pycryptodomex (>=3.20.0,<4.0.0)
25
26
  Requires-Dist: pydantic (>=2.6.3,<3.0.0)
27
+ Requires-Dist: pydantic-extra-types (>=2.7.0,<3.0.0)
26
28
  Requires-Dist: pydantic-xml (>=2.9.0,<3.0.0)
27
29
  Requires-Dist: requests (>=2.31.0,<3.0.0)
28
30
  Requires-Dist: requests-pkcs12 (>=1.24,<2.0)
@@ -43,6 +45,9 @@ The underlying API sends and receives XML documents. Each of these request or re
43
45
 
44
46
  After the data has been converted and added to the outer request object, it is sent to the appropriate server endpoint via a Zeep client. The client certificate is also injected into the request using a PCKS12 adaptor.
45
47
 
48
+ ## Domain
49
+ The domain to use when signing the content ID to MTOM attachments is specified when creating the client. This is not verified by the server, but it is used to generate the content ID for the MTOM attachments. As such, it is important to ensure that the domain is correct.
50
+
46
51
  # Serialization
47
52
  This library relies on Pydantic 2 and the pydantic-xml library for serialization/deserialization. As such, any type in this library can be converted to not only XML, but to JSON as well. This is extremely useful if you're trying to build a pass-through API service or something similar.
48
53
 
@@ -142,7 +147,7 @@ from mms_client.utils.web import ClientType
142
147
  cert = Certificate("/path/to/my/cert.p12", "fake_passphrase")
143
148
 
144
149
  # Create a new MMS client
145
- client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert)
150
+ client = MmsClient(domain="mydomain.com", participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert)
146
151
 
147
152
  # Create our request offer
148
153
  request_offer = OfferData(
@@ -176,14 +181,14 @@ There's a lot of code here but it's not terribly difficult to understand. All th
176
181
  If you want to test your MMS connection, you can try using the test server:
177
182
 
178
183
  ```python
179
- client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, test=True)
184
+ client = MmsClient(domain="mydomain.com", participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, test=True)
180
185
  ```
181
186
 
182
187
  ## Connecting as a Market Admin
183
188
  If you're connecting as a market operator (MO), you can connect in admin mode:
184
189
 
185
190
  ```python
186
- client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, is_admin=True)
191
+ client = MmsClient(domain="mydomain.com", participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, is_admin=True)
187
192
  ```
188
193
 
189
194
  ## Auditing XML Requests & Responses
@@ -202,7 +207,7 @@ class TestAuditPlugin(AuditPlugin):
202
207
  def audit_response(self, mms_response: bytes) -> None:
203
208
  self.response = mms_response
204
209
 
205
- client = MmsClient(participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, plugins=[TestAuditPlugin()])
210
+ client = MmsClient(domain="mydomain.com", participant="F100", user="FAKEUSER", client_type=ClientType.BSP, cert, plugins=[TestAuditPlugin()])
206
211
  ```
207
212
 
208
213
  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,6 +221,10 @@ This client is not complete. Currently, it supports the following endpoints:
216
221
  - MarketQuery_AwardResultsQuery
217
222
  - RegistrationSubmit_Resource
218
223
  - RegistrationQuery_Resource
224
+ - ReportCreateRequest
225
+ - ReportListRequest
226
+ - ReportDownloadRequestTrnID
227
+ - BSP_ResourceList
219
228
 
220
229
  We can add support for additional endpoints as time goes on, and independent contribution is, of course, welcome. However, support for attachments is currently limited because none of the endpoints we support currently require them. We have implemented attachment support up to the client level, but we haven't developed an architecture for submitting them through an endpoint yet.
221
230
 
@@ -9,31 +9,33 @@ mms_client/schemas/xsd/mi-report.xsd,sha256=XEHhHCGgK4aeYsmObIrlzkvV8UhbirgoysAE
9
9
  mms_client/schemas/xsd/mpr.xsd,sha256=QcnuKFm1WkyZfT_56cINHldZkR-3pU4nHSbFKHkIQS0,69149
10
10
  mms_client/schemas/xsd/omi.xsd,sha256=benkYeno_HF6BOIv7gAT79dWz00JccS3XilPLBCKVIU,31524
11
11
  mms_client/security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- mms_client/security/certs.py,sha256=kNCUFmy18YIxkWKu3mdMmlxmHdft4a6BvtyJ46rA9I4,1489
13
- mms_client/security/crypto.py,sha256=M7aIllM3_ZwZgm9nH6QQ6Ig14XCAd6e6WGwqqUbbI1Q,2149
12
+ mms_client/security/certs.py,sha256=Gy-CuSsdLPFeoPH_sEYhY67dI5sy6yJ8iTwlysRKT1s,3018
13
+ mms_client/security/crypto.py,sha256=u9Z6nkAW6LbBqUzjIEbZ-CcqdkMJ9fqvdX7IXTTh1EI,2345
14
14
  mms_client/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- mms_client/services/base.py,sha256=DavXAfWqSqcxfgbAFDj-9nj2DYL5YTMTPWHUM8aaL9s,26309
16
- mms_client/services/market.py,sha256=7eVqbgkfSip-GAAFnjetFbtmFILOGI6Gb8YISTiMh6w,9031
15
+ mms_client/services/base.py,sha256=4G8Ie5B56JGxDPL-T5t1ytC0c0kpSkQq3PJC5O-hEco,29604
16
+ mms_client/services/market.py,sha256=DUtnzWRLmTrTgZ4jo93B0S5Pq9K7dEtAGWYWbTbe5rA,9524
17
17
  mms_client/services/omi.py,sha256=UG1zYkFz0sFsEbhE6P0CLoAOZZOyEshkZ_b7D_e3CjQ,626
18
- mms_client/services/registration.py,sha256=ryj2WKJoBzRU1r6Svbl2MyGOG0H5aEYAK6HQWL9kYaA,3815
19
- mms_client/services/report.py,sha256=ZXYDaknPCnSYZI857QHbkzst1Pez_PrKFudVF9bQB7Q,642
18
+ mms_client/services/registration.py,sha256=tPJo-cBYURH5KkpxMQqWvZW6IqelzoBm5x6jzkJy-C0,3822
19
+ mms_client/services/report.py,sha256=hgRvjVxy8Hvbj5hQb0GMyDW0-1kMW2XFS5iKfO90YZY,6258
20
20
  mms_client/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  mms_client/types/award.py,sha256=BWE9V_KHXpg_cW1LZsetVrPs2hZDOklvRpNnoZtmR3k,14139
22
- mms_client/types/base.py,sha256=VQCr50CL1SnnPcO1EYGHa4rrkHBtXs-J8psWLJWoHJY,9710
23
- mms_client/types/enums.py,sha256=YJ58FbhyQ0TVlf8Z-Dg1UfVu8CurY5b21Cy5-WYkJ0I,1629
22
+ mms_client/types/base.py,sha256=VYXnUkEKcI1ki6Sk0ekklDLKDLkv03xrfbSFzzV_RXk,11240
23
+ mms_client/types/enums.py,sha256=hALMuqRChLUJ1Eglll5R5mkYLpcO-ZIaEBps3MjkTg0,2534
24
24
  mms_client/types/fields.py,sha256=pa5qvQVwEr8dh44IGHyYqgJYTYyTIeAjBW6CylXrkP0,14785
25
25
  mms_client/types/market.py,sha256=IbXsH4Q5MJI-CEvGvZlzv2S36mX_Ea02U11Ik-NwSxQ,2706
26
26
  mms_client/types/offer.py,sha256=KosFiKRMnt7XwlLBUfjHUGHiWzrMJUPPhGQMxgdeepM,6791
27
27
  mms_client/types/registration.py,sha256=Nir73S3ffpk0O_fnTD2alFaqV1k67_8dcyyduXvPBI4,1381
28
+ mms_client/types/report.py,sha256=ogfzIMvQeGBR_21JVHqQo1fqBZY7ExuRlpj6nNcKRcU,23044
28
29
  mms_client/types/reserve.py,sha256=pLV47w_749EIVhj0tUuJdWdHBBEl0-v10oVioccgxnU,2667
29
- mms_client/types/resource.py,sha256=TQnY3JLHRgQhQrG6ISquw-BQgKSr8TGuqn9ItWxWz_w,65974
30
- mms_client/types/transport.py,sha256=DPjWs34UW915GkUCJWKuDZmsjS6mRdRXgcGISduN_Bc,4399
30
+ mms_client/types/resource.py,sha256=TNQM51SLxnkjSlyJ2Sh-8Ph1-rNgkz3JKrAgI6qSHEg,65284
31
+ mms_client/types/transport.py,sha256=PZ7mDKeH8rGOVONk0ZH5herft71PFF-MUpp3uB57WXo,4395
31
32
  mms_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
33
  mms_client/utils/auditing.py,sha256=JDcvNo4ul66xPtDeeocn568yIe8fhh-jM11MWP-Kfes,2057
33
34
  mms_client/utils/errors.py,sha256=6k-NOjGZyTbTUISzN7B4JrmU2P8cwjpFFmFC7kJOQFQ,3005
34
- mms_client/utils/serialization.py,sha256=k0_fBm-yoRZV2AMiickSyauoDyA8i7uIPU6JjfQWx4Q,29638
35
- mms_client/utils/web.py,sha256=-abdVxSi7c6xQYsZObbj0yXwGI5VWthr5KtWDyLBCM4,10156
36
- mms_client-1.6.0.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
37
- mms_client-1.6.0.dist-info/METADATA,sha256=FSz-AvooX7RCU5vZ8BC1nhXINBlF3EFhitTc3ZngIh8,16025
38
- mms_client-1.6.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
39
- mms_client-1.6.0.dist-info/RECORD,,
35
+ mms_client/utils/multipart_transport.py,sha256=O374vPh2j29_CSjkWnIaPJfiabRSGNpQvNQcUODdkDM,8871
36
+ mms_client/utils/serialization.py,sha256=weXZQOqAiQ4ga-vAVz8PQ1JR_iX2iN0lyMimqqC3mio,33783
37
+ mms_client/utils/web.py,sha256=7c6Ghs3Y52cm2ge-9svR39uQjr2Pm2LhX9Wz-S1APa4,10816
38
+ mms_client-1.8.0.dist-info/LICENSE,sha256=awOCsWJ58m_2kBQwBUGWejVqZm6wuRtCL2hi9rfa0X4,1211
39
+ mms_client-1.8.0.dist-info/METADATA,sha256=eyLCuzX2tua2TvhouQRP5CBRPs45bLEJboNf22rhkE0,16590
40
+ mms_client-1.8.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
41
+ mms_client-1.8.0.dist-info/RECORD,,