mms-client 1.5.1__tar.gz → 1.6.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.
Files changed (39) hide show
  1. {mms_client-1.5.1 → mms_client-1.6.0}/PKG-INFO +2 -1
  2. {mms_client-1.5.1 → mms_client-1.6.0}/README.md +1 -0
  3. {mms_client-1.5.1 → mms_client-1.6.0}/pyproject.toml +1 -1
  4. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/services/base.py +6 -1
  5. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/services/market.py +33 -0
  6. mms_client-1.6.0/src/mms_client/types/reserve.py +71 -0
  7. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/utils/errors.py +15 -0
  8. {mms_client-1.5.1 → mms_client-1.6.0}/LICENSE +0 -0
  9. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/__init__.py +0 -0
  10. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/client.py +0 -0
  11. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/py.typed +0 -0
  12. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/wsdl/mi-web-service-jbms.wsdl +0 -0
  13. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/wsdl/omi-web-service.wsdl +0 -0
  14. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/xsd/mi-market.xsd +0 -0
  15. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/xsd/mi-outbnd-reports.xsd +0 -0
  16. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/xsd/mi-report.xsd +0 -0
  17. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/xsd/mpr.xsd +0 -0
  18. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/schemas/xsd/omi.xsd +0 -0
  19. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/security/__init__.py +0 -0
  20. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/security/certs.py +0 -0
  21. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/security/crypto.py +0 -0
  22. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/services/__init__.py +0 -0
  23. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/services/omi.py +0 -0
  24. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/services/registration.py +0 -0
  25. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/services/report.py +0 -0
  26. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/__init__.py +0 -0
  27. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/award.py +0 -0
  28. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/base.py +0 -0
  29. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/enums.py +0 -0
  30. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/fields.py +0 -0
  31. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/market.py +0 -0
  32. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/offer.py +0 -0
  33. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/registration.py +0 -0
  34. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/resource.py +0 -0
  35. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/types/transport.py +0 -0
  36. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/utils/__init__.py +0 -0
  37. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/utils/auditing.py +0 -0
  38. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/utils/serialization.py +0 -0
  39. {mms_client-1.5.1 → mms_client-1.6.0}/src/mms_client/utils/web.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mms-client
3
- Version: 1.5.1
3
+ Version: 1.6.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
@@ -209,6 +209,7 @@ This same input allows for the user to create their own plugins and add them to
209
209
 
210
210
  # Completeness
211
211
  This client is not complete. Currently, it supports the following endpoints:
212
+ - MarketQuery_ReserveRequirementQuery
212
213
  - MarketSubmit_OfferData
213
214
  - MarketQuery_OfferQuery
214
215
  - MarketCancel_OfferCancel
@@ -177,6 +177,7 @@ This same input allows for the user to create their own plugins and add them to
177
177
 
178
178
  # Completeness
179
179
  This client is not complete. Currently, it supports the following endpoints:
180
+ - MarketQuery_ReserveRequirementQuery
180
181
  - MarketSubmit_OfferData
181
182
  - MarketQuery_OfferQuery
182
183
  - MarketCancel_OfferCancel
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "mms_client"
3
- version = "v1.5.1"
3
+ version = "v1.6.0"
4
4
  description = "API client for accessing the MMS"
5
5
  authors = ["Ryan Wood <ryan.wood@electroroute.co.jp>"]
6
6
  readme = "README.md"
@@ -28,6 +28,7 @@ from mms_client.types.transport import RequestType
28
28
  from mms_client.types.transport import ResponseDataType
29
29
  from mms_client.utils.errors import AudienceError
30
30
  from mms_client.utils.errors import MMSClientError
31
+ from mms_client.utils.errors import MMSServerError
31
32
  from mms_client.utils.errors import MMSValidationError
32
33
  from mms_client.utils.serialization import Serializer
33
34
  from mms_client.utils.web import ClientType
@@ -459,7 +460,11 @@ class BaseClient: # pylint: disable=too-many-instance-attributes
459
460
  MMSClientError: If the response is not valid.
460
461
  """
461
462
  # Verify that the response is in the correct format. If it's not, raise an error.
462
- if resp.data_type != ResponseDataType.XML:
463
+ # NOTE: We're disabling the no-else-raise rule here because both comparisons are on the same enum so if one is
464
+ # removed then the other will raise an error. This is a false positive.
465
+ if resp.data_type == ResponseDataType.TXT: # pylint: disable=no-else-raise
466
+ raise MMSServerError(config.name, resp.payload.decode("UTF-8"))
467
+ elif resp.data_type != ResponseDataType.XML:
463
468
  raise MMSClientError(
464
469
  config.name,
465
470
  f"Invalid MMS response data type: {resp.data_type.name}. Only XML is supported.",
@@ -18,6 +18,8 @@ from mms_client.types.market import MarketType
18
18
  from mms_client.types.offer import OfferCancel
19
19
  from mms_client.types.offer import OfferData
20
20
  from mms_client.types.offer import OfferQuery
21
+ from mms_client.types.reserve import ReserveRequirement
22
+ from mms_client.types.reserve import ReserveRequirementQuery
21
23
  from mms_client.types.transport import RequestType
22
24
  from mms_client.utils.serialization import SchemaType
23
25
  from mms_client.utils.serialization import Serializer
@@ -34,6 +36,35 @@ class MarketClientMixin: # pylint: disable=unused-argument
34
36
  # The configuration for the market service
35
37
  config = ServiceConfiguration(Interface.MI, Serializer(SchemaType.MARKET, "MarketData"))
36
38
 
39
+ @mms_endpoint(
40
+ "MarketQuery_ReserveRequirementQuery",
41
+ config,
42
+ RequestType.INFO,
43
+ resp_envelope_type=MarketSubmit,
44
+ resp_data_type=ReserveRequirement,
45
+ )
46
+ def query_reserve_requirements(
47
+ self: ClientProto, request: ReserveRequirementQuery, date: Optional[Date] = None
48
+ ) -> List[ReserveRequirement]:
49
+ """Query the MMS server for reserve requirements.
50
+
51
+ This endpoint is accessible to all client types.
52
+
53
+ Arguments:
54
+ request (ReserveRequirementQuery): The query to submit to the MMS server.
55
+ date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults
56
+ to the current date.
57
+
58
+ Returns: A list of reserve requirements that match the query.
59
+ """
60
+ # NOTE: The return type does not match the method definition but the decorator will return the correct type
61
+ return MarketQuery( # type: ignore[return-value]
62
+ date=date or Date.today(),
63
+ participant=self.participant,
64
+ user=self.user,
65
+ days=1,
66
+ )
67
+
37
68
  @mms_endpoint("MarketSubmit_OfferData", config, RequestType.INFO, [ClientType.BSP])
38
69
  def put_offer(
39
70
  self: ClientProto, request: OfferData, market_type: MarketType, days: int, date: Optional[Date] = None
@@ -124,6 +155,8 @@ class MarketClientMixin: # pylint: disable=unused-argument
124
155
  days (int): The number of days ahead for which the data is being cancelled.
125
156
  date (Date): The date of the transaction in the format "YYYY-MM-DD". This value defaults to the
126
157
  current date.
158
+
159
+ Returns: Data identifying the offer that was cancelled.
127
160
  """
128
161
  # NOTE: The return type does not match the method definition but the decorator will return the correct type
129
162
  return MarketCancel( # type: ignore[return-value]
@@ -0,0 +1,71 @@
1
+ """Contains objects for MMS reserve requirements."""
2
+
3
+ from typing import List
4
+ from typing import Optional
5
+
6
+ from pydantic_extra_types.pendulum_dt import DateTime
7
+ from pydantic_xml import attr
8
+ from pydantic_xml import element
9
+
10
+ from mms_client.types.base import Payload
11
+ from mms_client.types.enums import AreaCode
12
+ from mms_client.types.enums import Direction
13
+ from mms_client.types.fields import power_positive
14
+ from mms_client.types.market import MarketType
15
+
16
+
17
+ class Requirement(Payload):
18
+ """Represents a reserve requirement."""
19
+
20
+ # The start block of the requirement
21
+ start: DateTime = attr(name="StartTime")
22
+
23
+ # The end block of the requirement
24
+ end: DateTime = attr(name="EndTime")
25
+
26
+ # The direction of the requirement
27
+ direction: Direction = attr(name="Direction")
28
+
29
+ # The primary reserve quantity in kW
30
+ primary_qty_kw: Optional[int] = power_positive("PrimaryReserveQuantityInKw", True)
31
+
32
+ # The first secondary reserve quantity in kW
33
+ secondary_1_qty_kw: Optional[int] = power_positive("Secondary1ReserveQuantityInKw", True)
34
+
35
+ # The second secondary reserve quantity in kW
36
+ secondary_2_qty_kw: Optional[int] = power_positive("Secondary2ReserveQuantityInKw", True)
37
+
38
+ # The first tertiary reserve quantity in kW
39
+ tertiary_1_qty_kw: Optional[int] = power_positive("Tertiary1ReserveQuantityInKw", True)
40
+
41
+ # The second tertiary reserve quantity in kW
42
+ tertiary_2_qty_kw: Optional[int] = power_positive("Tertiary2ReserveQuantityInKw", True)
43
+
44
+ # The minimum reserve of compound primary and secondary 1 in kW
45
+ primary_secondary_1_qty_kw: Optional[int] = power_positive("CompoundPriSec1ReserveQuantityInKw", True)
46
+
47
+ # The minimum reserve of compound primary and secondary 2 in kW
48
+ primary_secondary_2_qty_kw: Optional[int] = power_positive("CompoundPriSec2ReserveQuantityInKw", True)
49
+
50
+ # The minimum reserve of compound primary and tertiary 1 in kW
51
+ primary_tertiary_1_qty_kw: Optional[int] = power_positive("CompoundPriTer1ReserveQuantityInKw", True)
52
+
53
+
54
+ class ReserveRequirement(Payload):
55
+ """Represents a set of reserve requirements."""
56
+
57
+ # The area for which the reserve requirement applies
58
+ area: AreaCode = attr(name="Area")
59
+
60
+ # The requirements associated with the area
61
+ requirements: List[Requirement] = element(tag="Requirement", min_length=1)
62
+
63
+
64
+ class ReserveRequirementQuery(Payload):
65
+ """Represents a request to query reserve requirements."""
66
+
67
+ # The market type for which to query reserve requirements
68
+ market_type: MarketType = attr(name="MarketType")
69
+
70
+ # The area for which to query reserve requirements
71
+ area: Optional[AreaCode] = attr(default=None, name="Area")
@@ -38,6 +38,21 @@ class AudienceError(ValueError):
38
38
  super().__init__(self.message)
39
39
 
40
40
 
41
+ class MMSServerError(RuntimeError):
42
+ """Error raised when the MMS server returns an error."""
43
+
44
+ def __init__(self, method: str, message: str):
45
+ """Initialize the error.
46
+
47
+ Arguments:
48
+ method (str): The method that caused the error.
49
+ message (str): The error message.
50
+ """
51
+ super().__init__(f"{method}: {message}")
52
+ self.message = message
53
+ self.method = method
54
+
55
+
41
56
  class MMSClientError(RuntimeError):
42
57
  """Base class for MMS client errors."""
43
58
 
File without changes