Skip to content

Commit a870d48

Browse files
committed
docs: update release notes for v0.4.0 API features
Signed-off-by: Mathias L. Baumann <[email protected]>
1 parent b802d77 commit a870d48

File tree

4 files changed

+34
-41
lines changed

4 files changed

+34
-41
lines changed

RELEASE_NOTES.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ Initial release of the Frequenz Market Metering API client for Python.
77
## New Features
88

99
- `MarketMeteringApiClient`: Main client class for connecting to the Market Metering service
10-
- `stream_samples()`: Async iterator for streaming metering samples from Market Locations
10+
- `upsert_samples()`: Bidirectional streaming for upserting metering samples.
11+
- `create_market_location()`: Create a new Market Location.
12+
- `update_market_location()`: Update an existing Market Location.
13+
- `activate_market_location()`: Activate a Market Location.
14+
- `deactivate_market_location()`: Deactivate a Market Location.
15+
- `list_market_locations()`: List Market Locations with filtering and pagination.
1116
- `stream()`: Channel-based receiver for streaming with automatic reconnection
1217
- CLI tool (`marketmetering-cli`) for quick access to metering data
1318
- Support for multiple market identifier types:

mkdocs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ plugins:
102102
- mkdocstrings:
103103
default_handler: python
104104
handlers:
105-
paths: ["src"]
106105
python:
107106
options:
107+
paths: ["src"]
108108
docstring_section_style: spacy
109109
inherited_members: true
110110
merge_init_into_class: false
@@ -116,7 +116,7 @@ plugins:
116116
show_source: true
117117
show_symbol_type_toc: true
118118
signature_crossrefs: true
119-
inventories:
119+
import:
120120
# TODO(cookiecutter): You might want to add other external references here
121121
# See https://mkdocstrings.github.io/python/usage/#import for details
122122
- https://docs.python.org/3/objects.inv

src/frequenz/client/marketmetering/_client.py

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@
2929
MarketLocationsFilter,
3030
MarketLocationUpdate,
3131
MetricType,
32-
MetricUnit,
3332
PaginationParams,
3433
ResamplingOptions,
3534
RevisionSelection,
3635
UpsertResult,
37-
MarketLocationSample,
3836
)
3937

4038
DEFAULT_PORT = 443
@@ -159,16 +157,9 @@ def stream_timeout(self) -> timedelta:
159157
@property
160158
def stub(self) -> marketmetering_pb2_grpc.MarketMeteringServiceStub:
161159
"""The stub for the service."""
162-
# If we have an injected mock stub (for testing), return it directly
163-
if self._stub is not None:
164-
return self._stub # type: ignore
165-
166-
if self._channel is None:
160+
if self._channel is None or self._stub is None:
167161
raise ClientNotConnected(server_url=self.server_url, operation="stub")
168-
# This type: ignore is needed because we need to cast the sync stub to
169-
# the async stub, but we can't use cast because the async stub doesn't
170-
# actually exist to the eyes of the interpreter.
171-
return self._stub # type: ignore
162+
return self._stub
172163

173164
async def create_market_location(
174165
self,
@@ -186,7 +177,7 @@ async def create_market_location(
186177
market_location_ref=market_location_ref.to_protobuf(),
187178
market_location=market_location.to_protobuf(),
188179
)
189-
await self.stub.CreateMarketLocation(
180+
await self.stub.CreateMarketLocation( # type: ignore[misc]
190181
request,
191182
timeout=self._call_timeout_seconds,
192183
)
@@ -209,7 +200,7 @@ async def update_market_location(
209200
update_fields=update_pb,
210201
update_mask=update_mask_pb,
211202
)
212-
await self.stub.UpdateMarketLocation(
203+
await self.stub.UpdateMarketLocation( # type: ignore[misc]
213204
request,
214205
timeout=self._call_timeout_seconds,
215206
)
@@ -227,7 +218,7 @@ async def activate_market_location(
227218
request = pb.ActivateMarketLocationRequest(
228219
market_location_refs=[market_location_ref.to_protobuf()],
229220
)
230-
await self.stub.ActivateMarketLocation(
221+
await self.stub.ActivateMarketLocation( # type: ignore[misc]
231222
request,
232223
timeout=self._call_timeout_seconds,
233224
)
@@ -245,7 +236,7 @@ async def deactivate_market_location(
245236
request = pb.DeactivateMarketLocationRequest(
246237
market_location_refs=[market_location_ref.to_protobuf()],
247238
)
248-
await self.stub.DeactivateMarketLocation(
239+
await self.stub.DeactivateMarketLocation( # type: ignore[misc]
249240
request,
250241
timeout=self._call_timeout_seconds,
251242
)
@@ -280,7 +271,7 @@ async def list_market_locations(
280271
pagination_params.to_protobuf() if pagination_params else None
281272
),
282273
)
283-
response = await self.stub.ListMarketLocations(
274+
response = await self.stub.ListMarketLocations( # type: ignore[misc]
284275
request,
285276
timeout=self._call_timeout_seconds,
286277
)
@@ -311,9 +302,9 @@ async def upsert_samples(
311302
UpsertResult objects indicating success or failure for each sample.
312303
"""
313304

314-
async def request_generator() -> AsyncIterator[
315-
pb.UpsertMarketLocationSamplesStreamRequest
316-
]:
305+
async def request_generator() -> (
306+
AsyncIterator[pb.UpsertMarketLocationSamplesStreamRequest]
307+
):
317308
async for ml_ref, series in samples_stream:
318309
for sample in series.samples:
319310
yield pb.UpsertMarketLocationSamplesStreamRequest(
@@ -327,7 +318,7 @@ async def request_generator() -> AsyncIterator[
327318
response_stream = cast(
328319
AsyncIterator[pb.UpsertMarketLocationSamplesStreamResponse],
329320
self.stub.UpsertMarketLocationSamplesStream(
330-
request_generator(),
321+
request_generator(), # type: ignore[arg-type]
331322
timeout=self._stream_timeout_seconds,
332323
),
333324
)

src/frequenz/client/marketmetering/types.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
pagination_params_pb2 as pagination_params_pb,
1313
)
1414
from frequenz.api.marketmetering.v1alpha1 import marketmetering_pb2 as pb
15-
from google.protobuf import struct_pb2
16-
from google.protobuf import field_mask_pb2
15+
from google.protobuf import field_mask_pb2, struct_pb2
1716
from google.protobuf.timestamp_pb2 import Timestamp
1817

1918

@@ -265,11 +264,11 @@ class DataQuality(Enum):
265264
MISSING = pb.DATA_QUALITY_MISSING
266265
"""No valid value is available for this interval."""
267266

268-
def to_protobuf(self) -> pb.DataQuality:
267+
def to_protobuf(self) -> int:
269268
"""Convert to protobuf message.
270269
271270
Returns:
272-
The protobuf representation.
271+
The protobuf representation (integer enum value).
273272
"""
274273
return self.value
275274

@@ -373,13 +372,7 @@ def from_protobuf(cls, pb_obj: pb.MarketLocation) -> Self:
373372
EnergyFlowDirection(d) for d in pb_obj.supported_directions
374373
],
375374
time_resolution=TimeResolution(pb_obj.time_resolution),
376-
payload={
377-
k: v
378-
for k, v in pb_obj.payload.items()
379-
# Struct values are converted to native Python types automatically
380-
# by the protobuf library when accessing them via items(), but
381-
# we want to ensure we have a clean dict.
382-
},
375+
payload=dict(pb_obj.payload.items()),
383376
)
384377

385378
def to_protobuf(self) -> pb.MarketLocation:
@@ -691,11 +684,13 @@ def from_protobuf(
691684
# Here we assume it's always present or defaults to 0.
692685
revision=pb_obj.revision,
693686
update_time=update_time,
694-
resampling_method=ResamplingMethod(pb_obj.resampling_method)
695-
if isinstance(pb_obj, pb.MarketLocationSampleDetail)
696-
# Fallback to UNSPECIFIED if it's a simple MarketLocationSample
697-
# which does not have this field.
698-
else ResamplingMethod.UNSPECIFIED,
687+
resampling_method=(
688+
ResamplingMethod(pb_obj.resampling_method)
689+
if isinstance(pb_obj, pb.MarketLocationSampleDetail)
690+
# Fallback to UNSPECIFIED if it's a simple MarketLocationSample
691+
# which does not have this field.
692+
else ResamplingMethod.UNSPECIFIED
693+
),
699694
)
700695

701696
def to_protobuf(self) -> pb.MarketLocationSample:
@@ -704,12 +699,14 @@ def to_protobuf(self) -> pb.MarketLocationSample:
704699
Returns:
705700
The protobuf representation.
706701
"""
707-
return pb.MarketLocationSample(
702+
sample = pb.MarketLocationSample(
708703
sample_time=_datetime_to_timestamp(self.sample_time),
709704
value=self.value,
710705
quality=self.quality.value,
711-
revision=self.revision,
712706
)
707+
if self.revision is not None:
708+
sample.revision = self.revision
709+
return sample
713710

714711

715712
@dataclass(frozen=True)

0 commit comments

Comments
 (0)